Jump to content
Zenophon

Zenophon's ArmA 3 Co-op Mission Making Framework

Recommended Posts

zen_logo_small.png
* Credits go to CallMeSarge for this great logo

 

Introduction

Ladies and gentlemen, Armaholics of all ages, I am proud to present a work over a year in the making: Zenophon's ArmA 3 Co-op Mission Framework. My framework is a library of 252 SQF functions and 87 macros organized into a carefully designed API that is both easy to use and extremely powerful. The functions cover everything from manipulating arrays to an extensive task system. Each one has been meticulously designed and tested to provide useful features with minimal bugs and issues. The framework is designed so that each function is a logical building block that achieves a straightforward effect. The strength of the framework is that each small part fits together neatly with others, allowing you to quickly implement your mission design intuitively.

The framework works with any map and requires no addons. It is compatible with any mod because you choose which functions execute. There is effectively no performance impact to compile the entire framework, and every function has been diligently optimized. All 206 public functions are also carefully documented in an exacting style, and many resources are provided to help you learn to use the framework. The framework is created with these goals in mind:

  • Simple co-op fun for both players and mission makers
  • Bottom-up design using flexible pieces that you control
  • Truly random and dynamic missions without extra work for mission designers
  • Procedural mission design instead of manual placement using the editor
  • Eliminating large, static functions with assumptions about what you want in your mission
  • Server-oriented execution to create more efficient multiplayer missions
  • A simplification of locality and interacting with clients in multiplayer
  • A solid, powerful, and bug-free library to use as a foundation for your own code

The framework's many functions are divided into 14 categories with a specific purpose:

  • The Data functions are the foundation of the framework, supporting both simple and complex operations on arrays and strings.
  • The Dialog System allows dynamic creation and display of GUI's using only function calls.
  • The Fire Support system is a tool for mission makers, not players, to create any imaginable artillery, mortar, or airstrike.
  • The Loadout functions, including a full custom loadout system, provide every option you need to easily equip both players and AI.
  • The Math functions are auxiliary functions that deal with various 2D trigonometric operations on positions and polygons.
  • The Misc functions are just that, miscellaneous. They don't fit in anywhere else, but are still useful.
  • The Object functions deal with objects, and provide numerous ways to check on and interact with players, AI, and static objects.
  • The Objective system is designed to make side missions extremely simple for mission makers with just one line of code.
  • The Orders functions provide a tested and working way to make AI do things, and some offer simple but powerful randomization.
  • The Position functions generate and check random positions, allowing infinite randomization within your control.
  • The Preprocessor library offers both general and framework-specific macros that improve ease of use for many small tasks.
  • The Spawning functions allow you to spawn any object, AI or static, that you need and offer both straightforward and randomized spawning.
  • The Task system is a self-contained system meant to separate the mission maker completely from the issues of tasks, making any task operations simple.
  • The Trigger functions perform operations on tasks based on preset conditions and are designed to complement the Task system.

Download

Google Drive: (Go to file>download, or ctrl+s)
(.7z file) https://drive.google.com/file/d/0B-QFvxyAVKTUd0I4bFpPZTFLVTQ/edit?usp=sharing
(.zip file) https://drive.google.com/file/d/0B-QFvxyAVKTUS3dDcXdURG96bFE/edit?usp=sharing

Contact the author:
ZenophonArmAFramework@gmail.com


Changelog

 

 

3/19/22

 

 

  1. Fixed: Zen_OrderVehicleMove not working in some cases
  2. Fixed: Zen_OrderHelicopterLand not working in some cases

 

7/10/17

 

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

 

5/24/17

 

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

 

4/18/17

 

  1. Fixed: Framework preprocessor library prevents repeated definition
  2. Fixed: Zen_FindCenterPosition caused an error if given an empty array
  3. Fixed: Zen_UpdateControl would not update Map control type
  4. Improved: Zen_RefreshDialog accuracy of detected changes
  5. Improved: Zen_RefreshDialog causes less flickering
  6. Improved: Zen_RefreshDialog restores the currently selected list item
  7. Improved: Zen_SpawnVehicleCrew uses the crew classname defined by the vehicle's config if possible
  8. Added: Zen_CreateControl properties Event, MapPosition, MapZoom, and Transparency
  9. Added: Zen_RefreshDialog parameter for control change time
  10. Added: Zen_CreateControl type StructuredText
  11. Added: Zen_InvokeDialog parameter to prevent Esc key exits
  12. Documentation: Improved Zen_SpawnInfantry
  13. Documentation: Updated for Zen_InvokeDialog, Zen_RefreshDialog
  14. Documentation: Updated Notepad++ SQF language and autocompletion file with ArmA 1.68 stable commands

 

1/26/17

 

  1. New Function: Zen_SubdivideMarker
  2. Fixed: Zen_OrderAircraftPatrol, Zen_OrderBoatPatrol, Zen_OrderInfantryPatrol, and Zen_OrderVehiclePatrol now interpret their arguments correctly
  3. Fixed: Zen_InvokeDialog caused an error when attempting to show a list with no elements
  4. Fixed: Zen_OrderInfantryPatrol did not generate waypoints correctly for groups within the minimum radius
  5. Added: Zen_InvokeDialog parameter to allow user input to control their character while the dialog is open
  6. Added: Zen_InvokeDialog parameter to move the center of the dialog
  7. Added: Framework macro ZEN_FMW_Code_GetRemoteVar
  8. Added: Zen_CreateControl type Map
  9. Documentation: Fixed ZEN_FMW_MP_REClient, Zen_GiveLoadoutCustom and Zen_StringGenerateRandom Notepad++ hints
  10. Documentation: Added for ZEN_FMW_Code_GetRemoteVar, Zen_SubdivideMarker
  11. Documentation: Updated for Zen_CreateControl, Zen_InvokeDialog
  12. Documentation: Updated Notepad++ SQF language and autocompletion file with ArmA 1.66 stable commands


9/20/16

  • New Function: Zen_SpawnFlare
  • Fixed: Zen_ArrayFilterCondition argument check did not allow the first argument to not be an array
  • Fixed: Zen_ArrayInsertSlice argument check did not allow the first argument to not be an array
  • Fixed: Zen_CreateTemplate now correctly saves templates that are not on the ground
  • Fixed: Zen_IsCached gave the wrong default value when given an invalid identifier
  • Fixed: Zen_MoveAsSet shifted the set of objects to the height of the given position
  • Fixed: Zen_OrderAircraftPatrol, Zen_OrderBoatPatrol, Zen_OrderHelicopterLand, Zen_OrderInfantryMove, Zen_OrderInfantryPatrol, Zen_OrderVehicleMove, and Zen_OrderVehiclePatrol now give duplicate move and addWaypoints commands as a failsafe
  • Fixed: Zen_OrderVehicleDrop argument check now enforces the format of its second parameter
  • Added: Zen_ArrayFilterCondition parameter to filter nested arrays
  • Added: Zen_CreateControl property Angle
  • Added: Framework macros ZEN_FMW_Loadout_BasicInfantryPreset and ZEN_FMW_Loadout_HeavyInfantryPreset
  • Added: Zen_OrderVehicleDrop argument to delete the aircraft after making the drop
  • Added: Zen_UnCache can add units to a cache identifier
  • Added: Zen_InvokeTask, Zen_InvokeTaskBriefing, and Zen_UpdateTask parameters for task icon type
  • Improved: Zen_AreInArea, Zen_AreNotInArea, Zen_CreateTemplate, Zen_FindGroundPosition, Zen_IsForestArea, and Zen_IsWaterArea optimized using the new inArea command
  • Improved: Zen_ArrayGetRandomSequence, Zen_ArrayInsert, Zen_ArrayRemoveIndex, Zen_IsPointInPoly optimized
  • Improved: Zen_ArrayInsert, Zen_ArrayRemoveIndex, Zen_ArrayRemoveIndexedSlice, Zen_ArrayReplaceSlice print an error when an invalid index is given
  • Improved: Zen_ArrayRemoveDead now filters finished thread handles
  • Improved: Zen_ArrayRemoveNonLocal now filters non-local groups
  • Improved: Zen_Cache initial cache time significantly reduced
  • Improved: Zen_Cache and Zen_MoveInVehicle optimized using the new select {} command
  • Improved: Zen_CreateTemplate prints an error when it cannot find any objects
  • Improved: Zen_GetFreeSeats properly deletes its temporary object variables
  • Improved: Zen_ConvertToGroupArray and Zen_ConvertToObjectArray print an error when an incompatible type appears in a nested array
  • Improved: Zen_IsPointInPoly now checks that a given string is a marker
  • Documentation: Fixed for Zen_OrderVehicleDrop
  • Documentation: Fixed Notepad++ SQF language for black background displayed some SQF commands in the wrong color
  • Documentation: Added for ZEN_FMW_Loadout_BasicInfantryPreset, ZEN_FMW_Loadout_HeavyInfantryPreset, Zen_SpawnFlare
  • Documentation: Improved AI Caching demonstration
  • Documentation: Improved for ZEN_STD_Math_VectCartCyl, ZEN_STD_Math_VectCartPolar, ZEN_STD_Math_VectCylCart, ZEN_STD_Math_VectCylPolar, ZEN_STD_Math_VectPolarCart, and ZEN_STD_Math_VectPolarCyl
  • Documentation: Updated for Zen_ArrayFilterCondition, Zen_ArrayRemoveDead, Zen_ArrayRemoveNonLocal, Zen_GetTaskDataGlobal, Zen_InvokeTask, Zen_InvokeTaskBriefing, and Zen_UpdateTask
  • Documentation: Updated Notepad++ SQF language and autocompletion file with ArmA 1.62 stable commands

6/20/16

  • New Function: Zen_Cache
  • New Function: Zen_DeleteTemplate
  • New Function: Zen_GetCachedUnits
  • New Function: Zen_GetTemplateObjects
  • New Function: Zen_IsCached
  • New Function: Zen_RemoveCache
  • New Function: Zen_RemoveTemplate
  • New Function: Zen_UnassignCache
  • New Function: Zen_UnCache
  • Fixed: Zen_CreateTemplate shifted the height of all objects if some had non-zero height above the terrain
  • Added: Zen_GetUnitLoadout and Zen_GiveLoadoutCustom handle vehicles
  • Removed: Zen_GiveLoadoutCargo
  • Improved: Zen_ConvertToGroupArray and Zen_ConvertToObjectArray check that their entire argument is not void
  • Improved: Zen_CreateTemplate returns identifiers used in its object-oriented data structure
  • Improved: Zen_CreateTemplate saves the damage to specific parts, fuel, inventory, and animation states of vehicles
  • Improved: Zen_FindBuildingPositions checks that its raycasts hit the building of interest
  • Improved: Zen_SpawnGroup gives a specific error message for exceeding 144 groups per side
  • Documentation: Added for Zen_Cache, Zen_DeleteTemplate, Zen_GetCachedUnits, Zen_GetTemplateObjects, Zen_IsCached, Zen_RemoveCache, Zen_RemoveTemplate, Zen_UnassignCache, and Zen_UnCache
  • Documentation: Improved for Zen_FindBuildingPositions
  • Documentation: Updated for Zen_CreateTemplate, Zen_GetUnitLoadout, Zen_GiveLoadout, Zen_GiveLoadoutCargo, Zen_GiveLoadoutCustom, and Zen_SpawnTemplate
  • Documentation: Updated Notepad++ SQF language and autocompletion file with ArmA 1.60 stable commands

4/26/16

  • Fixed: Zen_AddFastRope failed to fastrope the player in some cases in MP
  • Fixed: Zen_FindCenterPosition caused an error when the first argument was not an array
  • Fixed: Zen_OrderFastRope makes AI in the player's group fastrope from FFV positions
  • Fixed: Zen_OrderVehicleDrop makes a teleported object inherit the aircraft's velocity
  • Added: Zen_AreIndoors and Zen_AreNotIndoors optional argument to use a more complex check
  • Improved: Zen_FindBuildingPositions gives points a buffer distance from walls and ledges
  • Improved: Zen_FindBuildingPositions does not return positions on the wrong side of a wall (i.e. outside the building)
  • Improved: Zen_SpawnParachute makes the parachute move with a fraction of the object's previous velocity
  • Documentation: Fixed paramsArray did not autocomplete
  • Documentation: Updated for Zen_AreIndoors and Zen_AreNotIndoors
  • Documentation: Updated Notepad++ SQF language and autocompletion file with ArmA 1.58 stable commands

3/20/16

  • New Function: Zen_CreateTemplate
  • New Function: Zen_SpawnTemplate
  • Fixed: Zen_AddSupportActionCustom let the player use the fire support menu from other units
  • Fixed: Zen_ArrayFindExtremum did not remove itself from the stack trace when given an empty or single element array
  • Fixed: Zen_FindCenterPosition overwrote its argument array
  • Fixed: Zen_FindCenterPosition printed some debug text
  • Fixed: ZEN_FMW_Code_InsertionPatrol did not handle land vehicles properly
  • Fixed: Zen_GetFreeSeats did not declare the identifier '_group' private, thus overriding its value
  • Fixed: Zen_GiveLoadoutCargo did not give backpacks
  • Fixed: Zen_SpawnInfantry spawned FIA units on East and Resistance sides by default
  • Improved: Zen_AreInVehicle and Zen_AreNotInVehicle now check their second argument
  • Improved: Zen_GetUnitLoadout now uses the type and count syntax for items
  • Improved: Zen_FindGroundPosition, Zen_GetAmbientClutterCount, Zen_IsForestArea, Zen_IsUrbanArea, and Zen_OrderInfantryPatrolBuilding now use nearestTerrainObjects
  • Documentation: Added for Zen_CreateTemplate, Zen_SpawnTemplate
  • Documentation: Improved Preprocessor Library documentation
  • Documentation: Updated JIP demonstration
  • Documentation: Updated Notepad++ SQF language and autocompletion file with ArmA 1.56 stable commands

2/9/16

  • New Function: Zen_AddSupportActionCustom
  • Fixed: Zen_AddFireSupportAction caused an argument check error in Zen_InvokeFireSupport
  • Fixed: Zen_AddFireSupportAction did not return a value of the correct type upon argument error
  • Fixed: Zen_AddFireSupportAction did not allow the caller to cancel the support when the guidance target was remote
  • Added: Zen_ExecuteCommand new command for setOxygenRemaining
  • Documentation: Fixed JIP demonstration had old code
  • Documentation: Added for Zen_AddSupportActionCustom
  • Documentation: Updated for Zen_GetFireSupportActionData, Zen_RemoveFireSupportAction, and Zen_UpdateFireSupportAction



Documentation

The included documentation explains how to use each part of this large framework in order to create missions. The documentation set features complete, standardized documentation organized by the categories for all of the framework's public functions. Further standard documentation, such as a changelog, FAQ, etc., are provided.

There is a series of 20 beginner tutorials to help first-time mission makers create simple missions using framework functions. For more experienced scripters, there are 15 intermediate demonstration missions and 8 full sample missions to show more advanced scripting techniques and more framework functions. Other helpful resources, including a Notepad++ SQF language, are provided.


Multiplayer and JIP

The framework was designed with the idea that the server should manage everything that it can, and few to no scripts should be run on the clients. Framework functions are designed to work in a multiplayer environment (dedicated servers too, of course) without the mission designer even considering how or why. Regardless if a mission is singleplayer or multiplayer, the framework's functions will do what they say they will without you changing anything.

The framework (or any function) cannot intrinsically deal with JIP and support it without any changes to your mission. Because you cannot reasonably be expected to divine what you need to do to make your usage of the framework JIP compatible, there is a JIP demonstration mission for you. Using the template there in your own mission, with a some customization, will make your mission JIP compatible.


Bugs

There will be bugs; this is not a final release, nor will it ever be. I have made every effort to test and debug all 194 public functions, and that that documentation agrees with the actual code. Bugs are not your fault; they come from some mistake within a framework function. It is not possible to produce bug-free software of this magnitude without mass public testing. This holds true whether or not the framework is still in beta. The development cycle of adding, improving, and fixing things goes on forever.

I assure you that I have every intention of fully supporting the framework for a long time. Fixing bugs and issues will always be my first priority over adding new features or tweaking things.


Feedback

I am not so arrogant as to think that I have considered everything, have a perfect design and implementation, and have judged the needs of ArmA mission makers fairly. I highly encourage you to submit any suggestion that occurs to you, even if you are not sure about it.

For simple feedback like 'I liked it' or 'I hated it', or if you have something important to say, this thread, PM, or email is fine. Concerning bugs, please post, PM, or email me a report (others will thank you for improving the framework) with every possible detail.

Concerning issues with understanding and using framework functions, please make use of every resource you have available to you. If you have a technical question about a more obscure function, feel free to look at the source code and experiment with it. If you really cannot figure something out, PM or email me with the information needed to help you.

Your issues, bugs, and feedback are important to me. This framework is important to me, and I am not going to 'get bored' or 'have real life issues' a month after release, leaving you with bugs. I have invested a lot of time into this framework, and I will continue to do so.


Editor Limitations

The framework can be the only resource used to create your mission, or you may use it in conjunction with the editor and your own scripts. However, you cannot use any framework function in an object's init field, a trigger's condition, etc, in the editor. You can still use framework functions in places in the editor that do not execute instantly upon mission start, such as a trigger's activation field.

I have no plans to change this; it seems like a significant problem, but it is in fact advantageous once you learn how to create and organize your mission using external scripts. Your mission will be better organized and easier to change and debug with all of its code and function calls in a few SQF files. There is nothing that can be done in the editor that cannot be done with scripting. There is a lot that can be done with scripting that cannot be done in the editor.

You might think that the editor is preferable to my complex framework. I can say with 100% confidence that my framework is quicker to use, more reusable, easier to test and debug, more effective, and more powerful than the editor. You will achieve better missions more quickly once you learn to use the framework.


What the Framework is Not

First, the framework is not a magic black box that generates lots of features for you with a few inputs. This is not a system of mission templates that lets you create a 2-hour combined arms mission in 5 minutes. This is not a random mission generator, it is not a resource for players. It is a tool for mission makers.

Second, the framework does not implement abstract systems. This means things that do not achieve a direct effect in the game world or perform a concrete operation. I will never add a wounding system, weapon resting, team killing protection, points and scoring, respawn, or anything else that is superfluous to the mission itself.

Third, the framework does not control the mission, your implementation does. The framework does not run any functions unless you call something (most functions also call other framework functions). There are no hidden functions observing the mission and guessing what you want next. Almost every action must be done by you manually, and others are optional.

Finally, the framework is not a collection or compilation of various people's work. Everything in the framework is designed and coded by me without using any external libraries and other people's code (except for a few BIS functions for GUI stuff). I must be able to guarantee the quality and functionality of every line of code (nearly 16000 lines) if I claim to be the author of the framework. I have purposefully reinvented the wheel numerous times to allow this framework to provide the best experience possible.


Legal

In addition to the terms of the Legal.txt file (please read), the framework is also released under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0) license.


Conclusion

You might also not be very impressed yet, but I assure you that you will be. I have spent over 2000 hours creating this framework. Believe me when I say that this framework is worth your time.


Credits

MimirAesir, Tutorials
MooseMan (https://forums.bistudio.com/user/906086-pellelil/), Zen_SpawnFlare

  • Like 10

Share this post


Link to post
Share on other sites

Hey, looks good! One question without getting deeper into your library: Why did you decide not to use CfgFunctions?

Share this post


Link to post
Share on other sites
Hey, looks good! One question without getting deeper into your library: Why did you decide not to use CfgFunctions?

I didn't like the _fnc_ part it put in the name; I prefer a more manual approach so I can name functions any way I want. There are also other global variables that need to be initialized before mission start, so I didn't want to split up the compile process.

Also, I don't want to deal with functions working/not working at preInit or postInit. I have purposefully delayed compilation until the Init.sqf to make things more straightforward and prevent people from scattering code all across unit init fields in the editor.

This clarifies client/server interaction, so mission makers are coding the first actions that happen from init.sqf and from the server's perspective, which most framework functions were designed for. The commands meant to start the init.sqf also do more than compile. They declare some more variables and functions, create side centers for spawning, detect JIP, etc.

Share this post


Link to post
Share on other sites

Wow you put in a lot of work in the framework and especially its documentation. Well done mate!

Share this post


Link to post
Share on other sites

Congrats Zenophon good work,

Work with this framework for my coop's soon.

Share this post


Link to post
Share on other sites

Great work, i currently checking it out ! :)

Share this post


Link to post
Share on other sites
Guest

Thanks for informing us about the 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

Zen, is there a way to add classnames from another custom unit mod? Llet's say I am running the Aggressors mod and want only the Middle Easter units to spawn, is there a way to make this happen?

Edited by chondo999

Share this post


Link to post
Share on other sites

In general, all the functions related to directly spawning people and vehicles can spawn addon units, and everything spawned using the framework can be 100% controlled by the mission maker. The framework does not use any preset lists of units that spawn. Whenever it spawns soldiers or vehicles randomly, it dynamically reads the config files looking for certain kinds of objects.

Specifically to your question, I assume you mean spawning soldiers using one of these functions:

  • Zen_SpawnGroup
  • Zen_SpawnInfantry

For Zen_SpawnGroup, you can simply list the classnames from the addon units as they appear in the editor or the readme of the mod. This is the fastest, simplest option to get addon units into your mission. For example:

_group = ["mkSpawn", <Array of Addon Classnames Here>] call Zen_SpawnGroup;

This will spawn the soldier objects in order at 'mkSpawn' and return the group. You still might want to set the AI's skill though, using Zen_SetAISkill.

For Zen_SpawnInfantry, getting addon units requires a little more work and some basic knowledge of config files. You need to provide information about certain config file values. However, you then get to use the features of Zen_SpawnInfantry, such as a randomized number and type of units.

You must open the config files in the editor, then find the addon units classnames under cfgVehicles (BIS really needs to add a search/filter option). The values for parameters 5 and 6 are called 'vehicleClass' and 'faction'. See Zen_SpawnInfantry documentation for parameters 5 and 6. For example:

_group = ["mkSpawn", east, 0.3, 5, <vehicleClass value (String)>, <faction value (String)>] call Zen_SpawnInfantry;

This will spawn 5 random soldiers whose side, vehicleClass, and faction match the arguments at 'mkSpawn' with skill 0.3 and return the group.

For vehicle spawning functions, you can give classnames just like Zen_SpawnGroup. However, the crew of the vehicle (for those functions that create it) will be from the vanilla pool of units (they cannot default to anything else). You should first spawn the vehicle empty, using Zen_SpawnVehicle, then spawn the addon crew and put them inside like so:

_vehicle = ["mkSpawn", <Addon Vehicle Classname (String)>] call Zen_SpawnVehicle;
_crew = [_vehicle, <Array of Addon Classnames Here>] call Zen_SpawnGroup;
0 = [_crew, _vehicle, "All"] call Zen_MoveInVehicle;

The vehicle at 'mkSpawn' now has all possible positions filled with addon units from the group. Just be sure to list the right number of classnames for that particular vehicle. You could also use an empty vehicle from the editor instead of spawning one in the code. This lets you put any crew you want into any vehicle.

Finally, if you want to directly generate the classname lists the functions are using, the function to use is Zen_ConfigGetVehicleClasses. See the demonstration mission entitled RandomBattle.Altis for a very detailed explanation of that function and what I just posted about config values.

Share this post


Link to post
Share on other sites

Thanks. Another question, Zen. Patrolling units always have their weapons up, in combat mode, as if they already know enemies are nearby. I was wondering if there was a way of spawning a patrol unit that, initially, starts with its weapon down, in safe or careless mode.

Share this post


Link to post
Share on other sites
Thanks. Another question, Zen. Patrolling units always have their weapons up, in combat mode, as if they already know enemies are nearby. I was wondering if there was a way of spawning a patrol unit that, initially, starts with its weapon down, in safe or careless mode.

This is a good suggestion. I did not think of it, and both Zen_OrderInfantryMove and Zen_OrderInfantryPatrol lack a parameter for AI behavior. The default behavior is 'aware' mode.

Adding a behavior parameter to both functions is a very fast improvement, and will be included in the next release, which is most likely tomorrow.

Share this post


Link to post
Share on other sites

Awesome project you've made here. I've been going over it all, quite comprehensive.

Great job.

Edit: my patrol scripts have default safe/yellow/limited with parameter options that dictate any combo available. Sometimes you want to have unique patrols.

Another thing I've been working on is behaviour after sharing knowsAbout values from a script. In essence I have a small script that monitors

"side knowsAbout otherside > xValue"

and then, depending on parameters, groups will share the value (by reveal) with other units within a certain distance. As knowsAbout levels fall, some behaviours/settings might go down (ie limited speed) but why would "awareness"? My thought if one group identified player as an enemy, and radioed nearby groups, none of those groups would ever go back to "safe", they would always be "on thier guard".

Just sharing thoughts ;)

Edit: a question. do you have a function to have the last member of a patrolling group join the next nearest group (if within specified distance)? I started putting that in mine so the lone unit would be more effective in another group, or two lone units could combine. its just a check i made upon the next waypoint being issued (or in my case, moving the waypoint as I only ever use one waypoint for a given patrolling group)

Edited by m0nkey

Share this post


Link to post
Share on other sites

I don't mean to pester with questions, but I am a noob and cannot help it. What, in layman terms, does this mean?

for [{_i=0}, {_i<3}, {_i=_i+1}] do {

for [{_j=0}, {_j<=_i}, {_j=_j+1}] do {

// Within the range of "i * 50" to "i * 50 + 50" generate a random position

_groupPos = [_objectivePos, [_i*100,_i*100+100]] call Zen_FindGroundPosition;

What does the first and last line interpret to?

My buddy told me " it's running three times. from 0 to 2", but 6 patrol groups end up spawning, not 3.

Share this post


Link to post
Share on other sites

Edit: my patrol scripts have default safe/yellow/limited with parameter options that dictate any combo available. Sometimes you want to have unique patrols.

The parameter for behavior is already tested and working internally for Zen_OrderInfantryMove and Zen_OrderInfantryPatrol. However, for both functions, combat mode is hard-coded right now. For Zen_OrderInfantryMove, I wanted the focus to be on moving without being distracted. However, if the AI encounters the enemy, their combat mode will increase from 'safe' to 'combat' dynamically. So, in this function, I am trusting the AI to react properly (obviously if they don't that's a bug/issue that can be fixed).

For Zen_OrderInfantryPatrol, the combat mode is hard-code to 'red' to improve AI aggression. Without this setting, I have found that the AI simply continue on to the next waypoint, with a significant delay due to taking cover etc., without really engaging their target. It also works with the detecting and attacking of nearby targets (see my explanation below).

Another thing I've been working on is behaviour after sharing knowsAbout values from a script. In essence I have a small script that monitors

"side knowsAbout otherside > xValue"

and then, depending on parameters, groups will share the value (by reveal) with other units within a certain distance. As knowsAbout levels fall, some behaviours/settings might go down (ie limited speed) but why would "awareness"? My thought if one group identified player as an enemy, and radioed nearby groups, none of those groups would ever go back to "safe", they would always be "on thier guard".

There is a demonstration mission about reveal and knowsAbout called Zen_AIShareInfo.sqf. Something like this algorithm is used by Zen_OrderInfantryPatrol to force patrolling groups to hunt down the enemy. However, in Zen_OrderInfantryPatrol, only the AI group that spots the enemy will go after them.

Generally, my goal with Zen_OrderInfantryPatrol is: have a simple, effective patrol function with good default behavior that can be interfered with easily. By that I mean that you can run threads parallel to Zen_OrderInfantryPatrol and do things to the groups, such as force a speed or behavior, monitor all of them, use reveal to simulate radio communication, etc., without really breaking anything.

To help and encourage people to set up their own AI share info and more complex management of the AI, I will add a parameter to Zen_OrderInfantryPatrol to disable the aggressive tracking. Once this is disabled, the only thing that makes Zen_OrderInfantryPatrol give new orders is if the group leader is 'unitReady'.

Though, if you are going interfere too much, there really is no need to use Zen_OrderInfantryPatrol at all. You are free to look at the source code and expand upon it or use parts of it in your mission. The scary legal stuff is mostly to prevent blatant theft. You can edit and modify things as much as you want and release a mission with it (it's not like I could stop anyone anyway).

Edit: a question. do you have a function to have the last member of a patrolling group join the next nearest group (if within specified distance)? I started putting that in mine so the lone unit would be more effective in another group, or two lone units could combine. its just a check i made upon the next waypoint being issued (or in my case, moving the waypoint as I only ever use one waypoint for a given patrolling group)

As state above, Zen_OrderInfantryPatrol is well prepared for interference, shuffling units around the patrolling groups will have little impact on the function. Creating new groups will make them unaffected by the function. If I were to code group joining, I would use Zen_FindMinDistance to make joining the nearest group easy.

However, I want to keep Zen_OrderInfantryPatrol fairly simple; I am not aiming for UPSMON-like quality and features. Every mission maker has an idea about how the AI should patrol, and Zen_OrderInfantryPatrol is there to provide basic functionality easily for people who don't care or don't have the experience to write complex patrol scripts.

---------- Post added at 20:15 ---------- Previous post was at 19:56 ----------

I don't mean to pester with questions, but I am a noob and cannot help it. What, in layman terms, does this mean?

for [{_i=0}, {_i<3}, {_i=_i+1}] do {

for [{_j=0}, {_j<=_i}, {_j=_j+1}] do {

// Within the range of "i * 50" to "i * 50 + 50" generate a random position

_groupPos = [_objectivePos, [_i*100,_i*100+100]] call Zen_FindGroundPosition;

What does the first and last line interpret to?

My buddy told me " it's running three times. from 0 to 2", but 6 patrol groups end up spawning, not 3.

It's no bother at all, I really enjoy coding and helping people; that's why I made a framework like this.

If memory serves, this snippet is from the demonstration solution to the warlord tutorial. The nested loops create a multiplicative effect. The '_i' (outer) loop will run three times. Each time it runs, the '_j' (inner) loop will run '_i' times. It is the inner loop that is spawning the groups, so if 6 groups spawn, the inner loop ran 6 times.

I will trace the code by replacing the variables with literals:

On the first run, _i == 0, and the '_j' loop runs 1 time and looks like this:

for [{_j = 0}, {_j<= 0}, {_j = _j + 1}] do {
   _groupPos = [_objectivePos, [0,100]] call Zen_FindGroundPosition;

On the second run, _i == 1, and the '_j' loop runs 2 times and looks like this:

for [{_j = 0}, {_j<= 1}, {_j = _j + 1}] do {
   _groupPos = [_objectivePos, [100,200]] call Zen_FindGroundPosition;

On the third run, _i == 2, and the '_j' loop runs 3 times and looks like this:

for [{_j = 0}, {_j <= 2}, {_j = _j + 1}] do {
   _groupPos = [_objectivePos, [200, 300]] call Zen_FindGroundPosition;

The sum of '_j' loop executions is 1+2+3 = 6. For each '_i' loop iteration, the distance used for Zen_FindGroundPosition increases; the distance does not increase when the '_j' loop iterates. The point of this is to show that you can use numerical patterns to make code very compact. This makes coding and maintaining things easier. You could also easily change things by multiplying '_i' by a different number or changing the upper bounds of '_i' and '_j'.

To make things a bit simpler, try replacing the '_j' loop header with this:

for [{_j = 0}, {_j <= 2}, {_j = _j + 1}] do {

Using a '2' literal instead of '_i'. The loops now follow a simpler mathematical pattern; the '_j' loop will have 3*3 = 9 executions.

  • Like 2

Share this post


Link to post
Share on other sites

Zen, thx a lot bro. Now I totally understand and am able to manipulate it to suit my needs.

Share this post


Link to post
Share on other sites

Introduction

Greetings fellow scripters and Armaholics, due to the pace of framework development, I have decided to start a weekly news report to coincide with each new release. In these updates, I will provide a detailed explanations of changes, go over plans and the roadmap for the next week, discuss framework design topics or concerns, request specific feedback, and continue to shamelessly advertise the framework in any way possible (but mostly the last one).

If these sound boring, you can skip them can download the latest version from the original post. For those that are even slightly interested, I assure you I will find many things to write each week about the framework.

This week sees a update to the original post, including the thread title, to make things as polished and professional-looking as possible. 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. As always, please bring an technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc.

Changelog

Before I get into the changes, I will briefly explain the changelog's organization. Each change is numbered, and prefixed with a general category. The categories are, in order of precedence, 'New Function', 'Fixed', 'Added', 'Improved', 'Updated', 'Tweaked', and 'Documentation'. The 'Documentation' category uses those same words to describe changes. Within each category, the changed function(s) are listed before a description of the change. Each line is then organized alphabetically by the name of the first function, with the functions also listed alphabetically.

This update has 13 changes, 5 of which are just documentation. Keeping the documentation updated and correct is about a third of the work. Only one obscure bug was fixed, and the rest are either changes for ArmA 1.24 or slight usability improvements.

7/16/14

  1. Fixed: Zen_SpawnInfantry did not allow nested skill range arrays for parameter 3
  2. Improved: Zen_ConfigGetVehicleClasses optimized
  3. Improved: Zen_GiveLoadoutBlufor, Zen_GiveLoadoutIndfor, Zen_GiveLoadoutOpfor 'guerrilla' loadouts now use new headgear and facewear
  4. Improved: Zen_GiveLoadoutCargo and Zen_GiveLoadoutCustom can now select randomly from nested arrays in sections that add all elements
  5. Improved: Zen_OrderInfantryMove and Zen_OrderInfantryPatrol now have a parameter for AI behavior state
  6. Improved: Zen_OrderInfantryPatrol now has a parameter to disable infantry following targets
  7. Improved: Zen_SetAISkill now gives group leaders a slight boost to all skills, except aiming accuracy
  8. Improved: Zen_SpawnParachute landing aesthetic quality greatly improved
  9. Documentation: Added and improved various FAQ.txt answers
  10. Documentation: Added 1.24 scripting commands to Notepad++ language and autocompletion file
  11. Documentation: Updated for Zen_OrderInfantryMove and Zen_OrderInfantryPatrol
  12. Documentation: Updated Custom Loadouts demonstration
  13. Documentation: Tweaked various files

Roadmap

Moving on, it was pointed out to me that for those learning the framework, there is a strange gap between the tutorials and sample missions. The demonstration missions are well explained, but they are very focused. The sample missions are just a massive wall of code that can be fairly daunting. Therefore, the sample missions will get new life next week, when I add comments (not too many or too simple), and an index with difficulty levels (see the demonstration readme for an example of that).

Remember, that which is not documented, does not exist. If you can think some aspect of using the framework that is missing from the documentation, by all means say something.

Also, hopefully a new function will make it out there next week: Zen_FindRoadDirection. As the title implies, it will give you the bearing of a stretch of road. It certainly doesn't make you want to jump out of your seat, but the benefit to getting convoys of vehicles spawned correctly is significant.

Function Spotlight

As users of my framework know, there are an enormous number of functions at your disposal. The amount of documentation that has to be sifted through can be extremely daunting. So, I have decided to include in each weekly report one function that, while obscure, is rather useful. The goal of this is to let mission makers know what they can get out of using the framework. 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_ArraySort.

While sorting an array might sound fairly boring, it offers two features that can make it useful. First, it is extremely fast, during testing, it sorted 10,000 integers in less than 4 seconds. This is obviously far beyond any normal use, but goes to show that a good algorithm pays off. If you are interested in the technical programming aspects, I will tell you that it uses a non-in-place unstable quick sort, with an insertion sort optimization, equal value optimization, and median pivot selection. You can look at the code yourself to see how it's done. There is also a shell sort, commented in the same file.

Second, it allows the use of a custom comparing function, so that it can sort objects, groups, and other data. You can use this to sort data any way that you want. For example:

// This sorts an array of arrays by the number of contents in each nested array
_sortedArray = [_array, {(count _this)}] call Zen_ArraySort;

// This is sorts an array of strings by how many non-whitespace characters are in each string
_sortedArray = [_array, {(count toArray ([_this] call Zen_StringRemoveWhiteSpace))}] call Zen_ArraySort;

From a design standpoint, it might have been better to use a real comparator rather than what is little more than a hashing function. The current design is to make things easier for new scripters. Writing a comparator with less, equal, greater tests is harder than just hashing some data type to a number. If you have some experience programming and use this function, I would like to know if you would prefer that it require true comparator.

Framework-Related News

For the general promotion of the framework, I am including a section specifically for news about framework-related scripts and missions that are released. The framework is not only for making missions, but can also be used as a library when writing scripts or even in addons. In the future, if you have released any content that uses the framework, PM me and I can advertise for you here with a link and short description. Also, I promise to play your mission/try your script and give you feedback.

Doing this doesn't just promote the framework, it helps all framework users see what kind of work can be done and will give them hints and ideas for their future projects. I firmly believe that the framework makes things easier for mission makers, and I want as many people as possible to benefit.

This week, seeing how it is the first week, I have only one piece of news.

I have released the first public mission using the framework. It is a infantry-focused, co-op mission where players try to survive as a small SF team in enemy territory. Check it out here:

http://forums.bistudio.com/showthread.php?180473-COOP-6-Evade-and-Survive

Give it a try, or at least look at the features list to see what kind of features the framework can provide. If you want to un-pbo it and look and the code, feel free.

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

For better or for worse, no bug reports have come in yet. I like to think that bodes well for the future. If you find any bugs, remember that they can only be fixed if you report them.

Also, I am really interested in how you are combining the framework with the editor. The two do not seem very compatible, looking at the tutorials and sample missions; however, I understand that people know and use the editor a lot. If you want, write in about what things you do where. Where you prefer to spawn units? How do you handle tasks? Are you using triggers in the editor or looping in code? All of your responses will help me make the framework the best experience possible for all users.

  • Like 1

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

Does anyone know if this framework works with the ALIVE mod? Or if it conflicts with the ALIVE mod in any way?

I know nothing about scripting. But our group has a leader who creates an ALIVE server for us. He custom scripts his own missions within the ALIVE framework. I'm wondering if he would benefit from using this mission creation framework to create some of his custom missions. We all like ALIVE, so I doubt we'll give up ALIVE anytime soon.

-V

Share this post


Link to post
Share on other sites
Does anyone know if this framework works with the ALIVE mod? Or if it conflicts with the ALIVE mod in any way?

I know nothing about scripting. But our group has a leader who creates an ALIVE server for us. He custom scripts his own missions within the ALIVE framework. I'm wondering if he would benefit from using this mission creation framework to create some of his custom missions. We all like ALIVE, so I doubt we'll give up ALIVE anytime soon.

-V

After looking through the ALIVE documentation briefly, it seems to be all modules for the editor. I see almost nothing about external scripting and if ALIVE's features can be called in code directly rather than using modules. I also don't see any documentation about what SQF functions it contains. ALIVE is also an addon that requires CBA. Obviously, correct me if I am wrong here about the scripting part.

My framework is not a system of modules and not use or require the editor in any way. It is not an addon and has no dependencies; it is a simple folder of scripts. I refer to it as a framework because it supports other people's code. It is an SQF function library that offers a massive number of features for those who cannot or have not coded such functions.

My framework is entirely compatible with all other mods and addons because it is just a library. The mission maker chooses what functions will run. It is very possible to create a mission using 99% scripting, which is how a prefer to make missions and why I created my framework. You could also just make use of one or two functions that you find interesting.

The functions themselves are mostly smaller parts. You would need to combine many of them to get a mission going. However, this is meant to give scripters much more control over their code. The framework is not just a few large scripts that you use with one line and magically have a full mission. It is a toolset for programmers and those who prefer scripting over the editor.

There are many documentation resources provided to help people learn how to use the framework, from how to use individual functions to creating very complex missions using SQF. I believe that almost everyone could benefit in at least a small way by using a few framework functions.

If the scripters in your group have read this and have further questions, I would be happy to answer any questions about my framework in this thread, through PM, or in email.

  • Like 1

Share this post


Link to post
Share on other sites
My framework is entirely compatible with all other mods and addons because it is just a library. The mission maker chooses what functions will run. It is very possible to create a mission using 99% scripting, which is how a prefer to make missions and why I created my framework. You could also just make use of one or two functions that you find interesting.

If I understand ALIVE correctly . . . it's a mod that places and tracks friendly and enemy forces via a database system . . . so they don't always have to be 3D objects that use a ton of CPU horsepower. By tracking the movement of all forces via database, and only having objects spawn in or out of the 3D world when players get close enough to engage them, or move far enough away for them to de-spawn . . . you can have a more persistent war environment (because the forces are always persistent & database tracked, they just pop into and out-of the 3-dimensional world when needed).

So it sounds like your script library SHOULD be 100% compatible with ALIVE, but you have not specifically tested your script library with the ALIVE mod to see if there are any problems.

Again, I know NOTHING about scripting. But IF I understand our group leader . . . he is currently making custom missions by using a combination of scripting multiplayer compatible events, and mixing that with some ALIVE features. For example: He may create a "locate and destroy an enemy weapons cache" mission that randomly places a enemy weapons cache somewhere in small town, within a 1/4th mile radius of a map marker that gets placed for all players to see. Then he tells the ALIVE mod that this town is a "high priority town", so if enemy soldiers or enemy vehicles who are randomly patrolling the town get attacked by us . . . the enemy quickly send in re-enforcements because having control of that town is high priority.

Thus, if we can sneak in and locate the objective . . . we're good. But if we have to attack enemies that spot us on the way in, we may quickly get attacked by re-enforcements.

It sounds like your library of scripts could possibly help him create custom missions that (HOPEFULLY) work well together with the ALIVE mod. I'll tell our group leader about this download and see if it could help him.

Thank you!!!

-V

Share this post


Link to post
Share on other sites

Zen, in order to increase the damage of the players weapons on opfor (like in your Evade OP) do I just place this command in the init: Zen_Damage_Increase = 8? What is the difference between this function and Zen_MultiplyDamage? There is documentation on the latter but not on the former.

Share this post


Link to post
Share on other sites
Zen, in order to increase the damage of the players weapons on opfor (like in your Evade OP) do I just place this command in the init: Zen_Damage_Increase = 8? What is the difference between this function and Zen_MultiplyDamage? There is documentation on the latter but not on the former.

Zen_MultiplyDamage is a function and Zen_Damage_Increase is a integer global variable that it uses. Zen_MultiplyDamage puts a handle damage eventhandler on the given units designed to increase only bullet damage to them. You must call the function for it to have any affect. A very brief overview of Zen_Damage_Increase is in the text documentation for Zen_MultiplyDamage. The need for a global variable is so that the damage increase can be changed at any time across all machines in MP.

Initially in development, it would simply multiply the damage by a constant, but this gets out of hand e.g. with .50 caliber rounds and such. Using a number like 7/8 allows the function to read the 'hit' config value for the bullet, add that number, then multiply the damage by the ratio of increased 'hit' to old 'hit'. The equation would look like so:

_damage = ((_hit + Zen_Damage_Increase) / _hit) * _damage;

The function's code doesn't look exactly like that, but you get the idea. The reason 7/8 is used is because that about doubles the damage of a 5.56mm NATO round, so it kills in 2 hits instead of 4. The 6.5mm rounds follow suite with 1-2 shot kills at close range.

Zen_MultiplyDamage is a scripting solution instead of config solution that mods would use. There are several strengths to this:

  • You could only apply increased damage to some units (seems unfair, but it's your choice)
  • You can change Zen_Damage_Increase at any time, even to a negative number (not less than -5)
  • The damage is increased for all bullets, even those from addons/mods, with needing to change anything
  • It is simple to use, and requires no mods or dependences

There are also a few disadvantages:

  • It conflicts with any other script or mod that uses handle damage eventhandlers
  • It is less efficient that just changing config values, as the eventhandler must run every time some one is shot

For example, you could do this at the end of your init.sqf, after you are done spawning everything:

0 = [allUnits] call Zen_MultiplyDamage;
Zen_Damage_Increase = 8;
publicVariable "Zen_Damage_Increase";

The publicVariable is necessary to send the correct value to any client machines, so everything is fair.

  • Like 1

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

×