-
Content Count
530 -
Joined
-
Last visited
-
Medals
Everything posted by Zenophon
-
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Possibly some combination of these: https://community.bistudio.com/wiki/addCuratorEditableObjects https://community.bistudio.com/wiki/addCuratorEditingArea Both claim they must be run on the server, but if you are spawning units on the server with the framework then no remote execution is required. If that doesn't work, what I would do next is open some of the curator .pbo files in ArmA's install directory (default is C:\Program Files (x86)\Steam\steamapps\common\Arma 3\Curator\Addons). However, a lot of Zeus is engine based (hence all the scripting commands), so I don't know if you will find anything useful. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
That error just means that you called Zen_CreateLoadout with the same loadout string name twice. Zen_CreateLoadout prints an error and stops rather than overwriting the old data, which it assumes you did not intend to overwrite. The error is harmless and does not affect giving the loadout. If you did intend to redefine a loadout, you must you Zen_UpdateLoadout as the error says. You just have to search your code for all uses of Zen_CreateLoadout and find the ones that repeat the name. Due to character limits on diag_log, if the loadout data is long enough, other parts of the error might not print to the log. Hints will also continue off the screen. However, the sidechat should print everything. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
First, I made a mistake about the loadout for JIP, it should be: 0 = [player, "BLUFOR_Loadout_01", false] call Zen_GiveLoadoutCustom; Or whatever string you gave the Blufor loadout that is created before 'sleep'. 'Loadout2' is undefined for the clients, but the loadout string itself points to valid loadout data. Second, if you have disabled friendly AI, new players are new objects. They must be handled differently in JIP and anywhere in the mission that depends upon the players. I rewrote the JIP demonstration about a month ago so that it can handle both cases (with and without AI). You can use that new template for the JIPSync.sqf file for your mission. The JIP code is more complex and still requires customization for your mission. For detecting JIP players during the main loop, the code should already be creating the players array from west units. It should not be in the forEach loop though: while {true} do { // Redefine the players array to account for respawn/JIP _players = [west] call Zen_ConvertToObjectArray; _players = [_players, {!(isPlayer _this)}] call Zen_ArrayFilterCondition; // some debug player sidechat str count _players; { // ...code... } forEach _townMkArray; // ...code... }; Are you sure that new areas that spawn (already spawned areas will not spawn more units) don't have the correct number of groups? Does the debug (you can change the chats to diag_log to make it easier to debug on a dedicated server) for the player count disagree with the number of groups that spawn? The VAS action is defined as a function 'Fnc_MPAddVASAction', which is used with BIS_fnc_MP in vehrespawn_mhq.sqf. BIS_fnc_MP is supposed to to call that function persistently for all JIP clients. If JIP clients don't see the action and clients at the start do, BIS_fnc_MP isn't working. You would have to manually implement calling that function for JIP for certain vehicles. You can modify Zen_JIP_Args_Server from any thread on the server, then use that element in JIPSync.sqf to put the action on the vehicle. Framework actions, repacking and giving magazines, don't work because the JIP code isn't set up for JIP players spawning into the mission, only for JIP players taking over existing AI. As I said, using the JIP demonstration code with a few tweaks should work fine. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
The issue might be that you can't put if statements as the bounds of a for loop. Try making the number of groups a variable returned from the if statement. You can then debug how many groups there are supposed to be, and if that many really are spawned. Since the loadout code isn't in the for loop, that bug is more likely the result of '_groupsArray' have the wrong value. _groupsCount = (if (count _players > 2) then {4} else {2}); player sideChat str _groupsCount; // Spawn 2 or 4 groups per marker depending on player count for "_i" from 1 to _groupsCount do { _spawnPos = [_x] call Zen_FindGroundPosition; _enemyGroup = [_spawnPos, ENEMY_SIDE, AI_SKILL, [4,8], "men", "SUD_USSR"] call Zen_SpawnInfantry; 0 = [_groupsArray, _enemyGroup] call Zen_ArrayAppend; }; player sideChat str _groupsArray; For the loadouts, 'loadout2' is defined twice. You can use Zen_CreateLoadout before sleep and before the clients exit to create the same loadout on all machines. However, you must give the loadout a string name (which is the same as 'loadout2') so that all client machines will have the same identifier as the server. Otherwise, 'loadout2' is not actually a loadout on a different machine, but that client has the same data stored under a different string identifier. loadout2 = [ /** Loadout Data */ ], "BLUFOR_Loadout_01"] call Zen_CreateLoadout; The name itself doesn't matter, so long as some constant string is provided. Then, in JIPSync.sqf, you must run that same loadout code that you ran on the server, just with an extra argument for remote execution. 0 = [player, loadout2, false] call Zen_GiveLoadoutCustom; Zen_AddFastRope is used on the vehicle that players can fastrope from, not on the players that can fastrope. If you want players to be able to fastrope from a helicopter, you need to call Zen_AddFastRope when the vehicle is spawned. You can then append that vehicle to Zen_JIP_Args_Server, so that JIP machines have the fastrope action on the helicopter. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Zen_ArrayFilterCondition has been modified to use code to evaluate elements. This improves performance (no more 'compile'), and allows the usage of predefined functions (and functional macros) to be used as the condition. On line 236, it should be: _players = [_players, {!(isPlayer _this)}] call Zen_ArrayFilterCondition; '_this' replaces '_x', and {} replace "". The logic of the condition does not change. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
You can edit Zen_SpawnVehicleCrew to change to classnames just like Zen_SpawnConvoy. That would affect every vehicle that Zen_SpawnVehicleCrew is used on, but since you don't want any CSAT at all there's no harm in changing those defaults. Obviously I would like to offer some feature that allows this without editing the source code, but this will work. You can also get the same results by using lower level functions (Zen_SpawnVehicle, Zen_SpawnGroup, etc.) with addon unit classnames. It takes more coding than editing framework work functions, but then you don't have to worry about which framework functions you have edited, etc. What I would want to do is put a lot of constants into a single header file and use the preprocessor, but because of an engine issue with the preprocessor, you have to copy that file into every directory so that the functions can use it. If users change it they would have to know it must be copied to take effect. This is already done with the existing preprocessor library; the difference is there's no reason to change those files. For function-specific constants, it might be better to put those into the compile scripts for each category. Of course, using true variables would work fine; however, changing them during the mission would affect things (and they would have to be publicVariable'd). There are no constant or final variables in SQF. I will keep thinking about it and try to find the best solution for next release. The only spawning functions that use hard-coded classnames are Zen_SpawnConvoy and Zen_SpawnVehicleCrew. For Zen_SpawnVehicleCrew, there are 5 classnames for 4 sides, so passing those as a argument is too much (documentation-wise). For Zen_SpawnConvoy, I am trying to use Zen_ConfigGetVehicleClasses to generalize what spawns, while keeping the default the same as it was hard-coded. That would allow giving a faction to Zen_SpawnConvoy. The rest of the spawning functions spawn either exactly what they are given or something random using Zen_ConfigGetVehicleClasses. However, some of these (e.g. Zen_SpawnAircraft) don't offer an option for faction when they could. For next release, I will add a faction parameter for about five spawning functions. Zen_CreateObjective being hard-coded is not that bad, as you are free to use the 'custom' objective type and spawn whatever you want, then take the spawned objects and manipulate them anyway you want (give them a crew, etc.). If I can add a way of changing fixed classnames, that will include changing e.g. officer classnames, etc. For Zen_SpawnFortification, I can just add a parameter for the classname of the weapon, then then make it optional with a default of what's already there. Improvements like that are very easy to make. From the log it seems that the function is using old code, the latest Zen_ArrayFilterCondition should call '_condition' without compiling it. Try downloading again, the date on Zen_ArrayFilterCondition.sqf should be 9/30. I would prefer not to accept donations, on the principle that creating the framework doesn't cost any money. However, seeing how my framework has helped mission makers is truly rewarding, and I am grateful for the appreciation and support of my users. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Introduction Greetings fellow scripters and Armaholics, in this latest installment, I will continue to discuss the development of the framework and, of course, shamelessly advertise the framework in any way possible. If this sounds boring, you can download the latest version from the original post. As always, the link to Google Drive for the .7z and .zip versions are already up to date. For those looking for older versions, go to file>revisions. The new version should be on Armaholic when Foxhound sees this or I PM him. Please bring any technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc. Changelog This week again contains few changes (more about that in the Roadmap section), involving various things that I found or thought of. Zen_FindBuildingPositions is continuing to improve by making sure that positions cannot be outside the building on ground level. It can also detect positions on balconies, walkways, etc. that are not on the roof. The argument specific macros are extended with two condition filters for Zen_ArrayFilterCondition. Both of them are fairly straightforward, and they provide filtering options that other functions can't. ZEN_FMW_ZAF_FT works the opposite of Zen_ArrayGetType; it removes the type rather than returning it exclusively. ZEN_FMW_ZAF_FS applies Zen_StringIsInString to every element that is a string, leaving those that are not. Zen_ArraySort never seems to disappear for too long (mostly because I really like sorting algorithms). It is now slightly faster when using a hashing function, and uses a less complex method when the given array is very small. That makes it even better at sorting e.g. 5-15 element arrays. Due to a slightly unrelated user-reported bug, Zen_ArrayRemoveDead now removes dead elements recursively in all nested arrays. Dead elements now include empty arrays, including arrays of dead elements. Also, Zen_ArrayRemoveNonLocal now removes from nested arrays as well. I also remembered that I keep forgetting to copy the Notepad++ SQF autocompletion file into the release folder. I apologize if you use Notepad++ with that; I would be lost without it. Finally, both FrameworkIntroduction.txt and the original post of this thread have been amended with a short description of the Preprocessor library. 10/1/14 Roadmap As you may have noticed from the Roadmap of previous releases (or lack thereof), there is a dwindling (almost nonexistent) list of things I want to improve or add. While a lot of users have contributed to the development of the framework, not many suggestions about major functions or features have been made. Because of the size of the framework and the time since release, I am not close to declaring a final release any time soon. The framework is entering a stage of extensive testing and refinement, more than I can accomplished by trying to break things with test scripts. Bugs and issues still exist, but not in the more popular functions or common combinations. Most of the issues users are having relate more to usage and general SQF coding than specific framework issues. Therefore, I will be changing the release schedule to a release every 2 weeks. These will be known as bi-monthly releases, their numbers will continue to count sequentially, and they will contain more changes at the cost of a longer wait. The first bi-monthly release is scheduled for 10/15/14. This does not preclude the interruption of this pattern by a release after one week (possibly changing the schedule of bi-monthly releases), if there are sufficient fixes and changes that have been well tested. 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_SpawnConvoy. The premise of this function is simple: provide automatic vehicle selection based upon side to generate a small, believable convoy using the vanilla ArmA 3 vehicles. However, some of the details of how this is done are important. _convoyVehicles = ["mkConvoy", west] call Zen_SpawnConvoy; _leadVehicle = _convoyVehicles select 0; _supplyVehicle = _convoyVehicles select 1; _troopVehicle = _convoyVehicles select 2; The entire crew of all of the vehicles are grouped together, such that an order directed at that group is carried out by the driver of the first vehicle, who is followed by the drivers of the other vehicles. Those trailing vehicles cannot take a different route unless their drivers are ordered to do so separately. The command 'move' gives orders to the entire group, and ordering a single unit is done with 'doMove'. An additional feature of Zen_SpawnConvoy is the inclusion of a random number of troops in the last vehicle. Accessing them is fairly simple, as is making them get out. You must them split them off into their own group before giving them orders. _troopUnits = (assignedCargo _troopVehicle); _units orderGetIn false; { unassignVehicle _x; _x leaveVehicle _vehicle; } forEach _units; _troopGroup = createGroup (side (_troopUnits select 0)); _troopUnits join _troopGroup; 0 = [_troopGroup, "mkDestination"] spawn Zen_OrderInfantryPatrol; A similar process can be used to split up the other vehicles into their own groups, whether or not they disembark. 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. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
I really don't know if there are any strategic locations on Altis, you can check that by seeing if Zen_ConfigGetLocations returns anything. To spawn groups in markers as the player moves, you need to make sure that this code is running in a loop during the mission. That code runs only once and is designed to be put into . Checking about every 30 seconds should be fine, longer if the player doesn't have access to vehicles. Also, make sure _player is still the player object, or a human if this is for MP. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
That's strange, as Zen_FindBuildingPositions is fairly rough around the edges. I assumed it would cause more problems than using built in building positions. Although a wiki or website for the documentation is possible sometime in the future, currently there would not be a lot for users to post. I have already written so much documentation that the only things left are lots of explanation and examples for various concepts and functions. Because this is just the beginning of the framework's life-cycle, mission makers are still adjusting to using by asking questions, making missions, etc. Eventually some of the stuff posted in this thread should be generalized and put into a wiki or knowledge base of some kind. You have put both the groups of spawned units and markers into the same array. Try this code, and just change the location types and see if it works for both: _townMarkers = [["NameVillage", "NameCity", "NameCityCapital"]] call Zen_ConfigGetLocations; _populatedTowns = []; { if ((([_x, _player] call Zen_Find2dDistance) < 1500)) then { _populatedTowns set [(count _populatedTowns), _x]; _groupsArray = []; for "_j" from 0 to (6 + random 3) do { _TownspawnPosition = [_x, 0, [], 1, [2, 500], 0, [1,0,10]] call Zen_FindGroundPosition; _EnemyTownGroup = [_TownspawnPosition, EAST, 0.6, [4,8]] call Zen_SpawnInfantry; 0 = [_groupsArray, _EnemyTownGroup] call Zen_ArrayAppend; }; _PatrolTown = [_groupsArray, _x, [], 0, "limited"] spawn Zen_OrderInfantryPatrol; }; } forEach _townMarkers; _townMarkers = _townMarkers - _populatedTowns; // Simple debug statements, making sure that your variables have the correct value player sidechat ("OPFOR Group " + str _EnemyTownGroup); player sidechat ("OPFOR Orders " + str _patrolTown); You can also use 'diag_log' instead of 'player sideChat str' to print the debug to the log. If you send me the log I have no problem searching through thousands of lines for errors. It's really just an approach using an alternative programming style (event-driven instead of function). Its implementation is complex because SQF is very functional, so things like strings and complex arrays must be used. If you don't like there's no reason to learn and use it. It would only be very useful for about 1% of missions. The bug appears random because it is caused by random vehicles spawning. The crew of the vehicle is being appended as an array of objects instead of a group. Somewhere in the spawning part you have something like these two lines: 0 = [_spawnedVehicle, ENEMY_SIDE] call Zen_SpawnVehicleCrew; 0 = [_groupsArray, (crew _spawnedVehicle)] call Zen_ArrayAppend; They should be: _crewGroup = [_spawnedVehicle, ENEMY_SIDE] call Zen_SpawnVehicleCrew; 0 = [_groupsArray, _crewGroup] call Zen_ArrayAppend; For next release, I will make Zen_ArrayRemoveDead recursively filter nested arrays and remove empty nested arrays (a empty array is 'dead'). -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Introduction Greetings fellow scripters and Armaholics, in this latest installment, I will continue to discuss the development of the framework and, of course, shamelessly advertise the framework in any way possible. If this sounds boring, you can download the latest version from the original post. As always, the link to Google Drive for the .7z and .zip versions are already up to date. For those looking for older versions, go to file>revisions. The new version should be on Armaholic when Foxhound sees this or I PM him. Please bring any technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc. Changelog This week features few changes but a lot of new additions. Zen_FindBuildingPositions is very effective at finding random positions inside any building. The positions will be at the correct height (i.e. for each floor) and not inside walls. You can also choose whether roof positions are returned. As of now, I think allowing roof positions can give you positions on ground level outside the building. Also, not allowing roof positions will prevent positions on balconies. I am working on implementing some tweaks to fix those, but they're not show-stopping. Six new macros have also been added, included three simple code snippets for insertions and spawning. This should remove some of the typing tedium for straightforward parts of your mission. For the avoidance of doubt, ZEN_STD_MTH_TPT is not the same as ZEN_STD_OBJ_TPT, the former transforms a position and returns it. The later moves an object and returns void. Both Zen_OrderInfantryPatrolBuilding and Zen_SpawnInfantryGarrison are updated to use Zen_FindBuildingPositions. This means that units will spawn and patrol anywhere inside a building. The functions get a reasonable number of random positions, then use them as if they were fixed building positions. Finally, Zen_ArraySort now supports both types of comparators. To be clear, a hash function that converts an argument to an arbitrary number, and a comparator is a ternary switch that returns -1, 0, or 1 if (1) is less, equal, or greater to (2). These are the best explanations I could find of each: https://en.wikipedia.org/wiki/Hash_function http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html 9/24/14 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). I want to thank everyone who has used and supported the framework. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Sorry, I meant to split up the debug before and after the check: { // _townMkArraySpawned lines up with _townPatrolsArray // _groupsArray is the array of groups patrolling the current town _groupsArray = [(_townPatrolsArray select _forEachIndex)] call Zen_ArrayRemoveDead; diag_log (_townPatrolsArray select _forEachIndex); diag_log _groupsArray; diag_log _x; diag_log (getMarkerPos _x); diag_log (getMarkerColor _x); diag_log ([_x, [], east] call Zen_GetAllInArea); // Checks if the enemy is gone or dead if ([_groupsArray, _x] call Zen_AreNotInArea) then { _x setMarkerColor "colorGreen"; // After check diag_log (format["Marker %1 clear, changing color to green", _x]); // 0 the indexes for this town _townMkArraySpawned set [_forEachIndex, 0]; _townPatrolsArray set [_forEachIndex, 0]; // Anything else to be done upon clearing the area }; } forEach _townMkArraySpawned; When the area clears correctly, all of it prints out as expected. The key is if it prints something different when it fails. This will also print a lot more debug, 6 lines for every spawned marker every ten seconds. I would put in some debug to show what the code is doing: _altisstrategicMarkers = [["Strategic", "StrongpointArea"]] call Zen_ConfigGetLocations; _populatedStrategic = []; { player sidechat str _x; if ((([_x, player] call Zen_Find2dDistance) < 1500)) then { _populatedStrategic pushBack _x; for "_j" from 0 to (8 + random 6) do { _StrategicspawnPosition = [_x, 0, [], 1, [2, 500], 0, [1,0,10]] call Zen_FindGroundPosition; _EnemyOpfStrategicGroup = [_StrategicspawnPosition, EAST, 0.6, [4,8]] call Zen_SpawnInfantry; player sidechat str _StrategicspawnPosition; player sidechat str _EnemyOpfStrategicGroup; }; }; } forEach _altisstrategicMarkers; player sidechat str _populatedStrategic; _altisstrategicMarkers = _altisstrategicMarkers - _populatedStrategic; It should print out each marker, the positions found, each group spawned, then all the markers that had groups spawned in them. Even if the player is too far away, at least all of the markers should print out. If nothing prints then there are not markers. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
You can try: _classList = ["Men", east, "All", "sfp_rus_faction"] call Zen_ConfigGetVehicleClasses; You can find the correct arguments in the config for the addon units; the first argument is called 'vehicleClass', the second is 'side', ignore the third, the fourth is 'faction'. Since you have the faction right, I can only guess that they are not 'Men'. For the grids not clearing, I would use Zen_TrackInfantry to debug where exactly all Opfor units are. Don't worry about spawning many threads; it's just debug. Then in the loop that checks each spawned marker for being clear, put in some debug like: diag_log (_townPatrolsArray select _forEachIndex); diag_log _groupsArray; diag_log _x; diag_log (getMarkerPos _x); diag_log (getMarkerColor _x); diag_log ([_x, [], east] call Zen_GetAllInArea); // After check diag_log "Area Clear"; If there are no unit alive or in the marker, and it's not cleared, then the fault is with the check. If nothing prints out for those markers, then the problem is with how they are being created and appended to the arrays. Try running the code just once without anything else, possibly in its own test mission. You can add in some debug to show if something is really happening. Also, make sure that all the variables are defined, arrays declared before appending to them, etc. _a_m_towns = [["NameVillage", "NameCity", "NameCityCapital"]] call Zen_ConfigGetLocations; _player = player; _TownArray = []; _a_m_remove = []; { if ((([_x, _player] call Zen_Find2dDistance) < 1500)) then { _a_m_remove pushBack _x; for "_j" from 1 to (3 + random 2) do { _spawnPos = [_x] call Zen_FindGroundPosition; 0 = [_spawnPos] call Zen_SpawnMarker; // debug _enemyGroup = [_spawnPos, east, 0.5, [4,8]] call Zen_SpawnInfantry; 0 = [_TownArray, _enemyGroup] call Zen_ArrayAppend; }; }; } forEach _a_m_towns; _a_m_towns = _a_m_towns - _a_m_remove; player sideChat str _TownArray; This code should put a marker on each group's spawn position, then print out all of the groups at the end. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Argument 6 of Zen_SpawnInfantry is an additional config filter value, along with the side and type ('Men' in this case). However, there are no objects of faction 'IND_F' on the East side. Thus the search will return nothing, and Zen_SpawnInfantry should print an error. In order to change the objects being spawned, you need to filter based upon valid config combinations. This involves looking through the config files for the values. All of this is explained in a lot more detail in the Zen_RandomBattle demonstration. The alternative is to use loadouts to change the appearance of units. You can apply uniforms from any side to spawned units; the loadout functions will force them on. Players will see no difference between true Resistance side units and East units wearing Indfor equipment, except for the voices (that can changed as well). -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Introduction Greetings fellow scripters and Armaholics, in this latest installment, I will continue to discuss the development of the framework and, of course, shamelessly advertise the framework in any way possible. If this sounds boring, you can download the latest version from the original post. As always, the link to Google Drive for the .7z and .zip versions are already up to date. For those looking for older versions, go to file>revisions. The new version should be on Armaholic when Foxhound sees this or I PM him. Please bring any technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc. Changelog This week's changes include plenty of interesting improvements to various functions (not that those preprocessor macros aren't interesting). A lot of them stem from an effort to improve ease of use when dealing with large indoor areas (like the ghost hotel). Zen_OrderInfantryPatrol now offers its chasing function for civilians, they should move to anyone they spot and follow them around for a while. This, of course, can be disabled with chasing parameter, which is now actually working (previously the argument was not overwriting the default value). Zen_SpawnParachute now allows you to provide any class of grenade (smoke, IR, etc.) that you want to be attached to the object as a signal. Classnames that are not technically magazines will not spawn. I am still working on how to filter out true firearm magazines effectively, so addon grenades can be used as well. Zen_RotateAsSet, Zen_SpawnGroup, and Zen_TriggerAreRescued now respect the height of positions and objects. You can now spawn a group in the air or rotate objects with different heights (they will still only rotate in the XY plane). All of these are meant for placing units inside large buildings that have few building positions. Zen_SpawnItemsOnTable has been improved by making sure the object is oriented to the table realistically. The items should also be shifted at random on the XY plane of the table top, with that shift oriented correctly to the table's direction. For optimizations this week, Zen_ConfigGetLocations now remembers the results of previous arguments, so using it to find hills, towns, etc. will only require processing for that set of arguments a single time. After that it will simply return the previous result. This is the same system used by Zen_ConfigGetVehicleClasses. Zen_SpawnAmbientVehicles has also been optimized thanks to Zen_ArraySort, so that it can detect valid towns and villages to spawn vehicles in order of distance. That way it doesn't have to look blindly for towns within the given distance. Finally, Zen_FindTerrainSlope has been very slightly optimized by using a different trig equation for the angle that requires one less operation. Fastroping has been generally improved by having Zen_OrderHelicopterLand force AI pilots to get even closer to the exact fastrope target. Zen_OrderFastRope will also make sure that ending point of the rope (where it collides with something) is as accurate as possible, provide the helicopter isn't moving. You can now reliably fastrope onto the roof of a medium-sized building, with less than 2 meters error from the given position. Also, the custom loadout system has been slightly modified so that a matching pair of weapon and magazine can give multiple of each. An example of this is shown in the custom loadout demonstration mission. The specifics are, of course, detailed and tedious, but the custom loadouts are meant to be an extremely flexible data structure. Finally, there are some new macros this week, including ZEN_STD_MTH_RNP to allow a random negative or positive direction to something and ZEN_STD_OBJ_TPT to alter an object's location by giving the change in its XYZ coordinates. I noticed that although BIS added lots of new commands for vectors recently, they don't offer coordinate system transformations. So ZEN_STD_MTH_VCC and ZEN_STD_MTH_VCP will change a Cartesian vector into a Cylindrical or Spherical (3d polar) vector. 9/17/14 Roadmap For next week, I plan on rewriting Zen_OrderInfantryPatrolBuilding to use a much better algorithm for creating move points in the building. Rather than just using the provided building positions, I aim to have it dynamically generate positions anywhere on the building, accounting for different floors, the roof, and different shapes of buildings. This could also be used in Zen_SpawnInfantryGarrison to improve the units' starting positions. If this is very successful, I will put it in to a new function that can generate infinite random valid points inside of any building, essentially providing a dynamic solution instead of fixed building positions. I am also planning on letting Zen_ArraySort use the old comparator style (it just hashes the element into a number). This will be a parameter, letting you choose the new style (a true comparator providing less-equal-greater results) or the old one. I am also going to offer a slightly different angle with some new macros, which will essentially be snippets of SQF code (2-6 lines) that appear extremely often. For example, a helicopter insertion, spawning and patrolling groups in a marker, etc. 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_GetUnitTasks. This function returns all task strings that are assigned to the given unit. This allows you to switch the focus from tasks to objects. For example, you have a thread running that assigns tasks to some units: 0 = _units spawn { // ... 0 = [_units, /* something */] call Zen_InvokeTask; // ... }; There are a lot of these tasks, all assigned to the same array of units. The tasks deal with markers that you have already placed. You don't want to deal with creating a data structure to send those task names back to your init.sqf thread and associate them with the markers. Instead, you use Zen_GetUnitTasks and Zen_GetTaskDataGlobal to check on the tasks: // Assume _markers is already defined as some objective zones // Assume the task titles are descriptive while {true} do { sleep 30; _tasksArray = [_units select 0] call Zen_GetUnitTasks; _tasksArray = [_tasksArray, "([_x] call Zen_AreTasksComplete)"] call Zen_ArrayFilterCondition; { _data = [_x] call Zen_GetTaskDataGlobal; _marker = [_markers, (_data select 3)] call Zen_FindMinDistance; switch (true) do { case (["Clear", (_data select 5)] call Zen_StringIsInString): { // if no enemies in _marker // task succeeded }; case (["Protect", (_data select 5)] call Zen_StringIsInString): { // if object of type "X" is not alive in _marker // task failed }; case (["Supply", (_data select 5)] call Zen_StringIsInString): { // if vehicle of _units is in _marker // task succeeded }; } forEach _tasksArray; }; That's a very incomplete example, but you can see how the task system allows you to work backwards from the objects by getting the tasks and their properties. You don't have to have the string name of the task to do something with it. 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 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. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
I can make it so that the custom loadout can given multiple random weapons, just as it already can give multiple random magazines. Next release this will work: ["weapons", [ [ [ "arifle_TRG21_MRCO_F", "launch_RPG32_F" ], "arifle_TRG21_GL_ACO_pointer_F", "LMG_Zafir_F", "srifle_EBR_DMS_F" ], "hgun_Pistol_heavy_01_F", "Rangefinder" ] ], ["magazines", [ [ [ ["30Rnd_556x45_Stanag", 9], ["RPG32_F", 4] ], ["30Rnd_556x45_Stanag", 9], ["150Rnd_762x51_Box", 4], ["20Rnd_762x51_Mag", 8] ], ["11Rnd_45ACP_Mag", 2], ["HandGrenade", 2], [ ["SmokeShell", 4], ["SmokeShellBlue", 4] ] ] ] This lets you choose which weapon the AT launcher goes with changes the probability of its appearance (putting it with all weapons gives 100% chance). If you don't want a connection between the rifle and having a launcher, then you must create two loadouts. If have 'Rifleman' and 'ATRifleman', then you can change their probability with this: 0 = [_unit, ["Rifleman", "Rifleman", "Rifleman", "ATRifleman"]] call Zen_GiveLoadoutCustom; The chance of a random AI having a launcher is 1:4, and so on as you add 'Rifleman' strings. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Then if I use that code in Zen_OrderInfantryPatrol, the civilians should move to any west unit just as an east unit would. The only issue is their behavior state, which could be 'combat'. I will change Zen_OrderInfantryPatrol so that if the group is civilian, then it uses: _group setBehaviour "careless"; The 'careless' mode cannot be changed by the AI, only with another setBehaviour command. That would make civilians less interested in finding cover or running around in circles. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Zen_SpawnItemsOnTable should put the object in the center of the table; it makes sense that getPosATL would return the center, at least for XY coordinates. If there is a problem with just some tables then the algorithm is not general enough. Zen_IsSeen sounds great, but it is not a simulation of AI sight. It just a mathematical determination of if a unit is possibly visible to the enemy. It could return true if you put your head around a corner 100 meters from the enemy. Zen_OrderInfantryPatrol uses knowsAbout because it more fairly represents what the AI can really see and accounts for their memory if the target has just gone out of sight. The distance to chase an enemy depends on the size of the patrol area. Units will leave their area if there is a clear target to attack, but will eventually give up based upon distance. The chasing enemy feature of Zen_OrderInfantryPatrol will work for civilians if findNearestEnemy (the command currently used) returns a valid target (I don't know if it does). Otherwise, I would have to rewrite the chasing feature to search for enemies using nearTargets. This would make things needlessly more complex for non-civilian groups (which is the intended use of the function). It's not possible stop civilians from running around crazy and not following move orders. As a workaround for that, you could spawn Blufor/Opfor units and put them in civilian clothes. They then function that same as regular soldiers, just without weapons. However, if they can be shot at, you would have to use setCaptive, which may bring some of those behaviors back. Lastly, making something that complex does deserve its own function/module. Zen_OrderInfantryPatrol is purposefully simple so that it can be flexible and easy to use. The main loop controlling the patrol is only 45 lines. If I provide a feature like civilian interaction I need to generalize it to fit almost any mission. Most mission makers have something very specific in mind for civilian interaction (like rushing a supply vehicle), so that makes generalizing very hard to do. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
That makes a good point about Zen_SpawnItemsOnTable. It should stop when it runs out of tables, not just when it runs out of classes. I will make that change for next week. Then you can do: // next release this will work for arrays of any length 0 = [([_objectClasses] call Zen_ArraySortRandom), _tables] call Zen_SpawnItemsOnTable; Thank you for appreciating the documentation. It admittedly was tedious to document that many functions in such an exact style. I believe it is important for the framework to have method to the madness. You will also be happy to know that I don't leave any deprecated functions around. For Zen_TriggerAreNear, yes the locations will be left as a object or group, so their positions will be reevaluated each iteration. This is the generic parser for the objective positions: _objPos = []; { if ((typeName _x) in ["OBJECT", "GROUP"]) then { _pos = _x; } else { _pos = [_x] call Zen_ConvertToPosition; }; _objPos pushBack _pos; } forEach _givenPos; -
Both the Chernarus and Takistan versions have been updated as well. Those versions differ by literally one line of code, so there was no reason not to.
-
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Introduction Greetings fellow scripters and Armaholics, in this latest installment, I will continue to discuss the development of the framework and, of course, shamelessly advertise the framework in any way possible. If this sounds boring, you can download the latest version from the original post. As always, the link to Google Drive for the .7z and .zip versions are already up to date. For those looking for older versions, go to file>revisions. The new version should be on Armaholic when Foxhound sees this or I PM him. Please bring any technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc. Changelog This release features a more conservative set of 14 changes, most of which are fairly minor. The most interesting addition are the first set of function argument macros. These macros represent a value (and some can accept arguments) that fits with certain argument(s) of a function. They are for Zen_ArraySort this week, providing some simple sorting comparators. Zen_ArraySort has also been modified to use a true comparator, rather than what was basically a hashing function. The comparator must return -1, 0, or 1 if the first value is less, equal, or greater than the second. This increases the complexity of using Zen_ArraySort, and decreases performance for extreme cases (10000 integers), but it allows more complex sorting without a significant performance hit for average array sizes (less than 500). For example, one of the macros offered is a alphanumeric string sort, which would have been nearly impossible before. Zen_FindGroundPosition has a small change that makes it return the given position, argument (1), if it fails to find a valid position. This sounds useless, but in fact it is very helpful because it does not let things spawn at (0,0,0). Although the given center might not be ideal, that point would work better than (0,0,0). Unfortunately, the way ArmA 3 preprocesses scripts does not allow #include directives to specify an 'up directory' command (normally ..\). This prevents functions from #include'ing the library if they are in a lower directory. The only solution seems to be coping the preprocessor libraries into all folders. You must also do this for your own functions in separate folders. This is annoying and there is nothing I can do about it. Please vote: http://feedback.arma3.com/view.php?id=9629. 9/10/14 Roadmap For next week, I will continue with some macros for Zen_FindGroundPosition, so that things like finding a good landing zone, a city street, etc. are much easier. 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_IsSeen. This function uses a simple, mathematical approach to determining if a unit would be visible by any enemies. For example, if you have a stealth mission in which the player pretends to be civilian, you can alert the enemy if the player gets too close and gets spotted: if ([player, 25] call Zen_IsSeen) then { player setCaptive false; }; Although that seems a little boring, you can make things more interesting: _seenCounter = 0; waitUntil { sleep 5; if ([player, 50] call Zen_IsSeen) then { _seenCounter = _seenCounter + 1; }; (_seenCounter > 5) }; Now you can vary enemy reinforcements, mission tasks, etc. based upon a quantitative level of player stealth. 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 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. ---------- Post added at 01:03 ---------- Previous post was at 00:10 ---------- Thank you for the compliments; I have probably put just as much time into documentation as I have coding. There is no online repository, GitHub or otherwise. You can make a local copy if you want to edit things, and I suggest something like WinMerge if you want to keep up to date with every release. Your first suggestion is a good one, in fact I may generalize it to allow any type of smoke grenade, chemlight, IR light, etc. The second suggestion is a bit trickier. If I allow one custom classname as the parameter, the vehicle would be filled by only that object. This removes the automation of class and side that makes the function easy to use. I could allow a list of custom classnames, for each possible kind of crew (tank, jet, etc.). However, this results in 5 classes for 3 sides (civilian never changes) giving 15 in total. I could search CfgVehicles dynamically for classes of a certain faction (which is typically how addon units are distinguished), but determining which of them is the correct crew type would in general be nearly impossible (you cannot assume 'pilot' etc. is in the classname). As a solution, I recommend using loadouts to simply make the unit look different. You can use Zen_GetUnitLoadout in a test mission to get addon units' default loadouts, and use the framework's custom loadout system to give certain ones to the crew. You can match the loadouts given to the types of the crew objects. This lets Zen_SpawnVehicleCrew indirectly decide the correct loadouts for the crew. -
Overview Greeting fellow Armaholics, this is a minor update to ensure the that the mission remains working smoothly. By user request, the positions of the objectives now prefer to be away from houses and dense forests. There is also a tiny fix to the color of one objective's marker. As always the mission has been briefly tested on a dedicated server, but that does not preclude the existence of bugs. Although the mission has changed very little, it indirectly benefits from all the improvements to my framework over the past few weeks. Changelog 9/10/14 Fixed: HQ steal intel task marker appeared in purple Improved: Objective locations now avoid houses and ambient clutter
-
Array problem ... help please
Zenophon replied to BEAKSBY's topic in ARMA 3 - MISSION EDITING & SCRIPTING
The assignment _x = ... in a forEach loop does not make that element reference/hold the new value. You must use the set command to explicitly assign to an index: _BLUveh = [[1200, "B_MBT_01_TUSK_F"],[900, "B_APC_Tracked_01_rcws_F"],[750, "B_APC_Tracked_01_AA_F"],[800, "I_APC_Wheeled_03_cannon_F"],[600,"B_APC_Wheeled_01_cannon_F"],[300,"B_MRAP_01_gmg_F"],[150,"B_MRAP_01_hmg_F"],[100,"B_G_Offroad_01_armed_F"]]; _BLUamo = [[200,"B_static_AT_F"],[200, "B_static_AA_F"],[150,"B_soldier_LAT_F"],[100,"B_G_Soldier_LAT_F"],[150,"B_GMG_01_high_F"],[100,"B_HMG_01_high_F"]]; //for Missile Specialist reduce asset costs by 10% if ((toLower secondaryWeapon player) in ["launch_b_titan_short_f", "launch_o_titan_short_f"]) then { { _x set [0, (_x select 0) * 0.9]; } forEach (_BLUveh + _BLUamo); }; You also don't need nested loops, each _x in the forEach loop is '[#, ""]', so _x[0] == #. I also changed the if statement to make it easier if there are many things to check. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Chondo is correct, you need to put the Zen_FrameworkFunctions folder into your mission folder. Copy-paste from the documentation FAQ: Also, see the section 'Step-wise Installation' in the topmost readme file (next to Shell.Stratis and Zen_FrameworkDocumentation). -
I cannot reproduce this issue with the current mission source code. Make sure you are not running any mods, and see if it works then. Also, try the version on Altis in case it's an issue with one of the addon maps. I will probably be releasing a small update soon, with a few fixes and improvements, to keep the mission 100% up to date and working with the latest version of ArmA.
-
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
The check for grids being clear is that no enemy are inside: if ([_groupsArray, _x] call Zen_AreNotInArea) then { This should be true if the enemy have fled the area. You can debug where exactly they are by putting this in the spawning part below the orders to patrol: 0 = [_groupsArray] call Zen_TrackInfantry; If all of the AI have left the area, but it doesn't complete in 10 seconds, then there is some bug that is causing some areas not to be checked. Zen_OrderInfantryPatrol should force the AI to stay in the area as much as possible, if that fails nothing can stop the AI from fleeing. For mission params, these take longer to setup but make your mission more flexible and user friendly, but they might let players make the mission too easy or too hard. If you prefer that your mission play at a certain difficulty in all circumstances, you can scale difficulty with code. You already have these lines: _players = [west] call Zen_ConvertToObjectArray; _players = [_players, "!(isPlayer _x)"] call Zen_ArrayFilterCondition; So when spawning enemy groups: // Spawn 2 or 3 groups per marker for "_i" from 1 to (if (count _players > 4) then {3} else {2}) do { Also, if you want AI to be included for purposes of spawning markers, use this line: _playersAndAI = [_players, "{isPlayer _x} count units _x == 0"] call Zen_ArrayFilterCondition; For the loadouts, the preprocessor is top-down, so you need to put definitions above where they are used in the file: #define WMDLOADOUT2 [loadout2] f_HandleRespawn = { // ... }; Regardless of when f_HandleRespawn is called, the preprocessor only parses it when it is defined.