-
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
In my framework, Zen_MP_Closure_Packet is the variable linked to a PVEH (this is the magic; the engine knows to run this code) on all machines. The EH just executes the code with arguments defined in Zen_MP_Closure_Packet, and you have complete control over where it executes. There are two methods to control remote execution on specific machines. First, code the logic into the function itself using any check necessary to stop execution using exitWith. Second, you can use publicVariableServer and publicVariableClient. BIS_fnc_MP is using the second method for you, and in the framework I just do it manually. For targeting an HC, you can use the macro ZEN_FMW_MP_REClient. There are other macros provided that automate different execution logic. // if HC is the object the client connects to ZEN_FMW_MP_REClient("f_SpawnOpfor", [_pos], HC) You can see the code for those macros in the library files, and there are two demonstrations about using Zen_MP_Closure_Packet. The PVEH code is in InitHeader.sqf. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
The AI mortar crew should be in the gunner seat and able to fire. You can use reveal and knowsAbout to give and check targets. If they don't fire automatically, try the command in the notes for fireAtTarget. I've tried to reproduce to '0 = call' generic error, but I haven't been able to find exactly what causes it. Technically, it should never be allowed because 0 is not a assignable identifier (commonly called a left-value) but rather a constant and a right-value. 'call ...' is always safe. I think most large rocks are objects that are part of the map, but not technically the ground. Thus, getTerrainHeightASL will not account for them. It's possible that units would spawn inside of very large rocks. I am working on making Zen_FindGroundPosition detect those large rocks and structures. The 'avoid house' parameter will likely become 'avoid large objects' parameter. I already is. Everything related to AI spawning and orders can be send to the HC machine to execute. The vast majority of framework functions can run on any machine; I just suggest running everything on the server for general neatness and performance. Whichever machine spawns an AI (using createUnit) becomes the owner of the AI. Simply put all AI spawning into global functions, then remote execute them on the HC (you can also account for an HC not existing and run them on the server). You can use BIS_fnc_MP or my framework's own remote execution method. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Thanks, that's actually a bug with Zen_GetTurretPaths. If a commander type position has smoke, flares, etc., it sees that as a weapon. I'll add in some logic to distinguish true weapons from countermeasures and equipment that are listed as weapons in the config. Zen_ConfigGetVehicleClasses already does that to distinguish armed and unarmed vehicles, but I also want to make it very general so that addon vehicles that use their own type of e.g. flare launcher are detected as well. At the very least it will work with vanilla vehicles and addon vehicles that use the standard BIS laser, flare, etc. I do not have a framework function that provides cleanup; a robust cleanup function would probably become its own system with internal data. You can code your own simple cleanup by just looping through the arrays of dead objects returned by the game engine. An example of that is in the Zen_InfantryPatrol sample mission. For removing any living units, you can use Zen_GetAllInArea to find any living units in an area, then delete them and any vehicles they are in. In the future, cleanup of both alive and dead units will probably be a feature of my AI caching script, which I'm leaning towards making an external script from the framework that requires it. You can also try letting the game engine handle dead cleanup, using description.ext params. I've never used them, so I can't tell you which are the best to use: https://community.bistudio.com/wiki/Description.ext There are seems to be a manual element to it, as you can use this command: https://community.bistudio.com/wiki/addToRemainsCollector -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
I'll add support for divers into Zen_OrderInfantryPatrol. Ideally, I could just set the height of the waypoint by looking at the terrain type and have the divers follow that height above the sea floor. However, divers might run up onto any land in the patrol zone though, so I might make an 'underwater' parameter. I verified the game cache on Steam, and I'm running 1.34 stable. I tried it again in a different test mission, and it still worked as intended. I've made some internal changes for bugs I found in addition to fixing the bugs reported, so that must be it. I'll just update the latest release to my internal version. Hopefully that's the last hotfix necessary for this release; it should fix everything that went wrong with this release. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Zen_SpawnVehicleCrew should spawn only true gunners (i.e. they have a weapon) when given only 'gunner'. This code works for me: _heli = [player, "B_Heli_Transport_01_F", 40] call Zen_SpawnVehicle; 0 = [_heli, west, "gunner", true] call Zen_SpawnVehicleCrew; The helicopter spawns and is missing the copilot, but the door gunners and pilot are there. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Zen_ConfigGetVehicleClasses uses the 'access' attribute to filter out a lot of base classes. Only classes with access = 2 are shown in the editor, and those the only classes Zen_ConfigGetVehicleClasses checks as possibilities. Without this optimization it's harder to identify and skip over unspawnable classes. You can use Zen_SpawnGroup as a workaround, as it only checks if the class is a subclass of "Man". Good find, I meant to set the default on the previous line as in Zen_SpawnVehicleCrew. I guess that's what happens when I test optional arguments only by giving the optional argument. The issue is only in MP because Zen_GiveLoadoutCustom does not remote execute itself with the correct arguments. I forgot that the default of optional arguments must be appended to the remote execution arguments. The loadout name being shown is the internal string name of the loadout. You can set this when the loadout is created using the second argument to Zen_CreateLoadout. ----- I've updated the latest framework version for the Google drive link with these two fixes. -
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 links to Google Drive for the .7z and .zip versions are already up to date. For those looking for older versions, go to file>revisions. The new version should be on Armaholic when Foxhound sees this or I PM him. Please bring any technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc. Changelog This release features another 18 changes, including some new features in the form of extra arguments to some common functions. The new function is Zen_IsWaterArea, which is a logical progression from functions like Zen_IsUrbanArea, etc. Although things looked grim for Zen_GetTurretPaths due to the new allTurrets command, Zen_GetTurretPaths has returned with new life. It can now filter types of turrets based upon what function that turret really has. It can distinguish between commander type turrets, such a copilot or observer with no weapons, true gunner turrets that have access to vehicle-mounted weapons, and fire-from-vehicle turrets for passengers. Of course, I can't test every possible vehicle, so give it a try and report any mistakes it makes. Zen_MoveInVehicle and Zen_SpawnVehicleCrew can now make use those turret types when they call Zen_GetTurretPaths. Zen_SpawnVehicleCrew also has a parameter to not spawn a driver. This adds a lot of flexibility for what positions are spawned or filled. The interesting new macro, ZEN_STD_OBJ_AnimateDoors, reads a vehicle's config file and opens or closes all of its doors for you. Zen_OrderFastRope, Zen_OrderHelicopterLand, and Zen_OrderVehicleDrop make use of this macro to add some realism to insertions and resupply drops. It turns out that setMass is the magic command for Zen_OrderExtraction and Zen_OrderInsertion, and, contrary to all physics logic, setting the mass to 0 makes it impossible to move an object. In reality, an infinite mass is impossible to move with a finite force. However, Bohemian physics aside, those functions now keep the helicopter on the ground at all times with no glitches or performance impact. Finally, in addition to the usual documentation updates and spot-check fixes, I have done a comprehensive proofreading of all text documentation (everything except function documentation and tutorials) to fix many errors ranging from typos, logical errors, and false information. 11/26/14 Roadmap While I'm still planning on doing an AI caching system at one point, I'm going to wait until I can bring some unique features that aren't already out there in other AI caching scripts. It may or may not end up as a separate script that requires the framework but isn't directly a part of it. 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_FindRoadDirection. This function makes it easy to place vehicles and road based objectives in a way that makes sense. Putting a car in the middle of the road doesn't make for a very realistic IED. A good example of placing a vehicle on the side of the road is taken from Zen_SpawnAmbientVehicles: _carPos = ["mkTown", 0, 0, 1, [1, 100]] call Zen_FindGroundPosition; _roadDir = [_carPos] call Zen_FindRoadDirection; _car = [([_carPos, 4, _roadDir + 90, "trig"] call Zen_ExtendPosition), "C_Hatchback_01_F", 0, 90 - _roadDir] call Zen_SpawnVehicle; Zen_FindRoadDirection will return one direction of the road; the other direction is obviously 180 degrees the other way. At crossroads, the function makes a decision for which road's direction to return. It does not return the average of the four roads, but picks one (the one with more area in the region it's searching) and returns that direction. You can also use it to place roadblocks convincingly: _roadblockPos = ["mkTown", 0, 0, 1, [1, 100]] call Zen_FindGroundPosition; _roadDir = [_roadblockPos] call Zen_FindRoadDirection; _car1 = [([_roadblockPos, 3, _roadDir + 90, "trig"] call Zen_ExtendPosition), "b_mrap_01_f", 0, _roadDir] call Zen_SpawnVehicle; _car2 = [([_roadblockPos, 3, _roadDir - 90, "trig"] call Zen_ExtendPosition), "b_mrap_01_hmg_f", 0, -_roadDir] call Zen_SpawnVehicle; _guards = [([_roadblockPos, 7, _roadDir, "trig"] call Zen_ExtendPosition), west, "infantry", 3] call Zen_SpawnInfantry; You can also put crew in the vehicles and make the infantry patrol in a small area around the checkpoint. Using Zen_FindRoadDirection and a little trigonometry you can quickly create good roadblocks or IED's that look as good as anything placed in the editor. 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. ---------- Post added at 21:19 ---------- Previous post was at 21:08 ---------- That demonstration names the actual config values that the function is looking at: vehicleClass = class types (1) textSingular = subtypes (3) faction = vehicle faction (4) You can look in the config files in the editor, find the addon unit, and find the values at those config entries. Alternatively, you can use SQF code to read those values for you, e.g.: systemChat str getText (configFile >> "CfgVehicles" >> (Classname of addon object) >> "vehicleClass"); All of them will use getText; you can also use 'copyToClipboard'. Once you have all the types, subtypes, and factions you want, enter them and the correct side into Zen_ConfigGetVehicleClasses. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
I can make Zen_SpawnVehicleCrew only spawn a driver or turrets; I'll add that as a parameter for the release tomorrow. However, the copilot position of helicopters is considered a turret (or any commander type seat on a ground vehicle), so the vehicle will only be missing a driver. I would have to inspect each turret and try to determine if it really has a weapon, which I'm fairly certain can be done. This warrants a the return of Zen_GetTurretPaths with some new features. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
That script looks very good. There's really no point in me duplicating all that work, so I won't write my own AI caching script until I can offer some unique features. As long as there's some AI caching script that works with the framework, it's not really a missing feature. I will look at existing AI caching scripts and see if there's some significant features I could offer that they don't. -
Overview Greetings fellow Armaholics, by user request I have updated this mission to use my latest framework. There are no direct changes to the mission. All of the improvements are the result of changes in my framework. In addition, the mission uses the my internal version of the framework, which includes a few simple fixes that are not in the latest public release. Changelog 11/17/14 Improved: Various improvements and fixes included in my latest framework
-
Overview Greetings fellow Armaholics, by user request I have updated this mission to use my latest framework. There are no direct changes to the mission. All of the improvements are the result of changes in my framework. In addition, the mission uses the my internal version of the framework, which includes a few simple fixes that are not in the latest public release. All three map version have been updated. Changelog 11/17/14 Improved: Various improvements and fixes included in my latest framework
-
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
This is the right place to post anything about using the framework. You can also PM me if you prefer; it's up to you. I'm going to quote myself here; all of this still applies even after four months. -
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 fixes some old issues and provides compatibility and improvements for 1.34 stable. The first new function is Zen_OrderSlingLoad; it gives you a simple way to have the AI sling-load vehicles without any player involvement. There are some minor fixes to arguments for Zen_OrderInfantryPatrol, Zen_SpawnAircraft, and Zen_SpawnHelicopter. Two macros have been renamed, to follow a more logical nomenclature, and there is a new macro, ZEN_STD_Code_SwapVars. Zen_SpawnItemsOnTable now treats the table as a rectangle instead of a circle. The helicopter engine on/off issue with Zen_OrderExtraction and Zen_OrderInsertion has finally been fixed by keeping the invisible helipad that Zen_OrderHelicopterLand generates. Something about the AI makes it take off when that landing spot isn't there. The two new helicopters have correct fast-roping rope locations in Zen_OrderFastRope, and the right doors open for both fast-roping and landing with Zen_OrderHelicopterLand. With the addition of fire-from-vehicle positions, the new 'allTurrets' command is used in several functions instead of Zen_GetTurretPaths (which is likely to be deprecated next release and removed entirely in a month). Finally, and I have saved the best for last, the very old issue with Zen_FindGroundPosition and limited angles in uneven markers (there were more points near the center and short sides) has at last been fixed. The function that does this, Zen_QuantizeAngles, is so named because the angles take discrete steps, or 'quanta' (as in quantum theory), rather than being continuous. The steps are not always equal, but rather are generated such that the areas of the arcs they sweep out inside the shape are equal. This produces an even distribution of areas instead of an even distribution of angles and thus a truly random selection of 2D points. The function that can actually use those quantum angles has been overhauled and made a public function, called Zen_FindPositionPoly. This week's function spotlight is about these two functions, as they warrant some examples and some explanation for those who are curious. 11/12/14 Roadmap The most significant addition now planned is an AI caching system designed to be perfectly compatible with the framework and designed similarly to other framework systems. It will provide a very open (i.e. documented) API that you can generalize to do almost anything by coding with small, functional parts (which also describes the entire framework). I might have a basic working build of this for next release. Zen_GiveLoadoutCustom will offer an 'additive' option, allowing the loadout data to give items without removing anything. It might also extend to replacing equipment in certain slots. Zen_GiveLoadout with be updated with that 'additive' parameter as well as a parameter for remote execution. This sounds minor, but it allows an arbitrary organization of loadouts. If you simply want to give all units a GPS (which everyone would have in 2035), that becomes a loadout with all of the features the loadout system provides. You can make very specific loadouts for certain styles of uniforms, equipment, etc. that you then combine into a final loadout. I also plan to improve Zen_OrderFastRope and Zen_OrderHelicopterLand to open the correct doors on every helicopter, as well as dynamically read the config files of addon helicopters and open their doors as well. There will also be a Zen_IsWaterArea to determine how much of an area is water. This would be useful for finding beaches, ponds, lakes, rivers, etc. It might also help artillery scripts decide not to fire 50% of their rounds into the ocean. Finally, although I very much want to use the new physics ropes to drastically improve the aesthetics and physics of Zen_OrderFastRope, I'm going to be honest and say it looks rather bleak. After a while experimenting with the new ropes, I don't see a simple engine-based way of attaching an object to any point on a rope and having the physics engine take over. I really hope BIS is planning to add fast-roping integrally as they did sling-loading. Otherwise, it's an unfortunate missed opportunity. 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_FindPositionPoly, and a bit of Zen_QuantizeAngles. As explained briefly in the changelog section, Zen_QuantizeAngles is a fundamental change in how a limited angle range is used. First, I will quickly show why the old method does not work. Assume you have a marker that is very uneven (e.g. it goes 100 meters East and West and only 10 meters North and South) and you can pick any angle from 0* to 360* (I will use compass angles, but the math is done with trig angles). If you randomly select from the continuum of angles, then getting 0* or 90* (or any angle) is equally likely. However, at 0*, the greatest distance to go is 10m, but at 90*, you have 100m within the marker. If you do this very many times, on average, the point will be close to the center (numerically, (5 + 50)/2 = 27.5m). So although we picked the angle at random, the point is biased towards the center. The intuitive reason that Zen_QuantizeAngles works is that it looks at areas rather than curves. Selecting a continuous angle at random does not account for the 2D shape, while looking at the area between two angles does. It follows that a 2D angle selection algorithm produces an even 2D distribution. The angle that gives the area is the difference between any two angles in the array generated by Zen_QuantizeAngles. That step will change as the radius from the marker's center does. Although it currently on deals with ellipses and rectangles (the only polygons in ArmA 3), it could be used for any closed 2D surface for which the radius can be defined as a function of the angle. Zen_QuantizeAngles is used separately from Zen_FindPositionPoly mostly for performance reasons. The angular quantization of a marker is not random; it is deterministic and predictable (i.e. running Zen_QuantizeAngles twice for the same arguments give the same result). Once the quantum angles have been calculated, you can use Zen_FindPositionPoly infinitely for the marker. This is what Zen_FindGroundPosition does, but you can now do the same thing (without all the filtering) faster with just these functions. // From the example above, corrected with angular quanta _quantumAngles = [[100, 10], 0, 0, 360, "rectangle"] call Zen_QuantizeAngles; for "_i" from 1 to 1000 do { _pos = ["mkTest", [100, 10], 0, "rectangle", _quantumAngles] call Zen_FindPositionPoly; 0 = [_pos] call Zen_SpawnMarker; }; That takes about 4.1 seconds for me, and using Zen_FindGroundPosition takes about 40.3 seconds without using any filters. If it has always bothered you that Zen_FindGroundPosition is slow (though it makes up for it in features), then you can now generate points 10x faster (an average of 4ms per point). If you've never noticed the issue that I'm making a big deal about, you can observe it for yourself now: // This is the result of the example without quantization for "_i" from 1 to 1000 do { _pos = ["mkTest", [100, 10], 0, "rectangle", [random 360]] call Zen_FindPositionPoly; 0 = [_pos] call Zen_SpawnMarker; }; The contents of the angles array for Zen_FindPositionPoly are arbitrary as long as they are numbers. Giving only one random angle is perfectly fine. If the marker dimensions where exactly equal, there would be no difference and you wouldn't need Zen_QuantizeAngles. However, observe the result of that code, and you can see why I've written such a long-winded explanation of this. 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
A caching system written in a similar style to parts of the framework (e.g. the task system) would probably be most compatible with it. I would use a data structure in an OO style with each abstract group represented by a string identifier. The data would basically include: The classnames of the units in the group (let this tell you the size of the group) The loadouts of each unit (this is optional, default loadouts will be fine at first) The position of the group The velocity of the group, if it is abstract (not spawned), (maybe their destination) I would then design cache and invoke functions to transition from spawned to abstract and vice versa. It is a good idea to get the basic system to work manually (i.e. calling the functions in a hard-coded test mission) before you create an automatic caching manager. The automatic manager would run on its own thread in a turn-based fashion operating on the current data regardless of what it is. Thus the proxy functions for caching, invoking, deleting, etc. work from any thread (i.e. the manager is subject to external interference). You can then introduce detector logic and data so that the manager can use the caching and invoking functions in a simple, logical way. I would leave it up the mission maker who can trigger the caching whether they are players or AI. The manager is also responsible for updating the group's position if they are not spawned. This basically involves some calls to Zen_FindGroundPosition for random patrols. When the group is spawned, the manager would translate those abstract movements into actual AI orders. That's how I would approach designing and coding this system. If you want to take the lead and code the system, I'm willing to help you with anything you need. Otherwise, I'll code it myself because it is a worthwhile addition that will make the framework an excellent stand-alone resource to create 40+ player co-op missions. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
When run, it automatically copies the preprocessor library files into all subdirectories. You can remove it if you want; it has no affect on missions. It's just to make coding the libraries easier for me. I left it in there in case mission makers want to change some preprocessor macros (not a good thing to do blindly) or add new ones. They must be copied due to this bug: Please vote: http://feedback.arma3.com/view.php?id=9629 Having unpbo'd (some of) ASR AI, it appears to change the AI's skill in a random range based upon some preset levels. I didn't see an obvious indicator of how it detected new units, although I'm sure it's able to do that. You could try calling Zen_SetAiSkill after ASR AI sets the units skill, but I don't know how you would determine when it did. Looking very briefly at the source code for TPWCAS, I see that all uses of 'setSkill' are switching between newly calculated values and the original skills of the unit. Thus, if you use Zen_SetAISkill before TPWCAS stores the skill value, that will be its default 'old' value. Ii also uses 'allUnits' to detect AI, so it will automatically update when new units are spawned with Zen_SpawnInfantry (or any spawning function). -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Then positions you can fire from are considered turrets in the config. I will have to filter those somehow to separate the two types of turrets. Also, I will definitely make functions to have the AI sling-load if BIS doesn't offer a one-line command to do it. '_helicopterAlpha' is a local variable to the script, the trigger executes in a different thread (i.e. different local namespace). You must name it 'helicopterAlpha' without the '_' to put the variable in the global namespace, which all threads share (scheduled and non-scheduled). You can also do so explicitly with this: _helicopterAlpha = [_heliSpawnPosAlpha, "B_Heli_Transport_03_F", 100] call Zen_SpawnHelicopter; missionNamespace setVariable ["HelicopterAlpha", _helicopterAlpha]; Someone asked about ALIVE a while ago, and I didn't really have a good answer for them because I don't use ALIVE. The difficulty is in combining the module system of ALIVE with the heavy coding of the framework because you have no link between the two. From what I understood from quickly looking at ALIVE, you have lots of options for the different modules but no access to the source API. If combining them doesn't work out, I'd be happy to help you write an AI caching script that's easy to use with the framework. It would not be that difficult to get basic features going like storing AI groups, their units, their loadouts, making them abstractly move, and getting it MP sync'd so the server or HC caches/uncaches groups based upon client location. Those are purposefully for a single waypoint. If you want many random waypoints, the patrol functions offer that. I assumed that anyone who wanted a series of fixed waypoints would use the editor. However, if you have several semi-random points, you can link them together: // Let _waypointArray be an array of positions // and _vehicle be some vehicle 0 = [_vehicle, _waypointArray] spawn { { _h_move = [(_this select 0), _x] spawn Zen_OrderVehicleMove; waitUntil { sleep 5; scriptDone _h_move; }; } forEach (_this select 1); }; Now, why didn't I just put that into Zen_OrderVehicleMove, etc.? What if you wanted the vehicle to do something at every waypoint? What if the waypoints could change while the vehicle is moving? It gives scripters more options at the cost of more coding. You can just make the above code a function and then have a choice between the two styles. You can then add some code to not make the vehicle stop at each waypoint, based upon its velocity and distance. -
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 The highlight of this release is a significant improvement to all the preprocessor macros; they have all been renamed to make them easier to use and recognize. The names are still relatively short, using abbreviations where the full word is obvious (e.g. 'OBJ' for object or 'veh' for vehicle). In addition, numerous new macros have been added, with many argument values for Zen_FindGroundPosition. There are also macros for waiting for a distance between objects and getting a vehicle's weapons. Accordingly the standard macro ZEN_STD_OBJ_VIA has been removed in favor of ZEN_FMW_CFG_VehicleWeapons, which uses a much better algorithm. The issue with Zen_OrderExtraction and Zen_OrderInsertion has been solved by simply letting the AI land normally and turn off their engines. If you are playing as the group leader during an insertion, ordering your subordinates to disembark early (e.g. when the helicopter is still in flight), may cause it not to land correctly. There's nothing I can do about this; the AI pilot responding to the disembark order is hard-coded in the engine. The most significant fix is for Zen_ReassignTask and Zen_RemoveTask, which both called a smaller function that could erase the task's data entirely. They both now modify the task correctly and allow further changes to work. Also, Zen_RotateAsSet has been fixed for markers and optimized using a different 3d transformation algorithm. Finally, a significant improvement to the documentation of many functions is the inclusion of their hidden parameter for remote execution. Almost every function that automatically remote executes itself in order to work from the server now has that argument explicitly listed in the documentation. I strongly recommend that you do not give that argument unless you know what its effect will really be. 10/29/14 Roadmap Very little is planned for next release, so any feedback is appreciated so that I have something to do. I will probably just focus on testing and mission-making. I think Zen_GiveLoadout should have a remote execute options as well, and there will be some more argument macros for Zen_SetWeather. 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_RotateAsSet. Having been improved this week, this function can serve for both logic transforms and randomization. For example, rotate some vehicles to the direction of the road they are on: // Assume _vehicles are spawned on a road _roadDir = [(_vehicles select 0)] call Zen_FindRoadDirection; _vehicleDir = [(_vehicles select 0), (_vehicles select 1)] call Zen_FindDirection; 0 = [_vehicles, _vehicleDir - _roadDir] call Zen_RotateAsSet; Recall that Zen_RotateAsSet rotates clockwise by default, so to rotate through trig angles (which go counter-clockwise) the rotation angle must by opposite than when using compass angles. Numerically, if _roadDir = 45* and _vehicleDir = 90* (trig), (* denotes degrees), then the rotation is 90* - 45* = 45*, which is > 0 and clockwise. You can also make use of Zen_RotateAsSet for randomization. Assume you have five fixed position objectives, which can be guarded by two patrol zones defined as markers. These markers are relatively small, such that they cannot cover every angle of approach. To add replayability, you can rotate those sets of markers randomly to cover the objects from random directions. Their size depends on the area around the objectives, so they have been placed in the editor. // Assume a naming convention like mk_obj#_mkr# for "_i" for 1 to 5 do { _markerArray = []; for "_j" from 1 to 2 do { _markerArray pushBack format ["mk_obj%1_mkr%2", _i, _j]; }; 0 = [_markerArray, random 360] call Zen_RotateAsSet; }; Of course, this works for any number of markers around any objectives. It will also work for objects, just use 'missionNamespace getVariable' to get the object from a string. 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. ---------- Post added at 02:48 ---------- Previous post was at 02:42 ---------- Sorry, I didn't see your edit for a few days. The code you add shouldn't affect tasks in any way. The issue could be the data being looked at when tasks are added, the reference unit used to get the tasks, or Zen_ReassignTask itself. Give it a try with the new release, and put in this debug: diag_log Zen_Task_Array_Global; diag_log (leader group player); diag_log (units group player); diag_log ([(leader group player)] call Zen_GetUnitTasks); // Just use Zen_ReassignTask, as in the JIP demo { 0 = [_x, player] call Zen_ReassignTask; } forEach ([(leader group player)] call Zen_GetUnitTasks); It should appear the the reference unit is a living object, and his tasks are those already assigned to players. Those tasks would then be given to Zen_ReassignTask, so the bug is in there if the tasks are correct. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Because true is not void; the return matches the documentation. I could use (nil) at the end and the effect should be the same, but I just chose exitWith. I could use true/false or 1/0 to indicate success or failure, but that's just a lesser version of throwing an exception. Since exception handling in SQF is somewhat lacking, I made all of the errors print everywhere that they can and stop the function. Thus functions that have nothing meaningful to return simply return void. You must call Zen_AddLoadoutDialog in the JIP sync code for the action to be added. Append the loadouts to Zen_JIP_Args_Server: Zen_JIP_Args_Server = [ ... , ["Light_AT_loadout","AA_loadout","Assault_loadout","Sniper_loadout","wm_Demo_loadout","Medic_loadout","Autorifleman_loadout","Heavy_AT_loadout"]]; Then in JIPSync.sqf, call Zen_AddLoadoutDialog using those loadouts on all the objects that should have the action: { 0 = [_x, (_serverArgs select 11), -1, false] call Zen_AddLoadoutDialog; } forEach [bLUFORLoadouts, MHQ1, MHQ2, MHQ3]; -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Thanks, I'm glad that all the time spent designing each function and how they fit together paid off. The exitWith explicitly returns void, rather than the value of the last line. Thus, it is safe to use '0 = call ...' or just 'call ...' without an error or putting an unknown value into your script when the call returns. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
After quite a bit of testing and looking through the code, realized that only one thing could be the problem. The only change to tasks for JIP is done by Zen_ReassignTask. I had assumed that it was working, but in fact it was not. I feel like I should have seen that earlier. Nevertheless, the bug is not directly in Zen_ReassignTask, but in a private function that it calls. This function is called Zen_CleanGlobalTaskArray and its file (of the same name) is in the Task System folder. The entire correct code for the function is this: // This file is part of Zenophon's ArmA 3 Co-op Mission Framework // This file is released under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0) // See Legal.txt private ["_cleanUnitsArray"]; { _cleanUnitsArray = [(_x select 1)] call Zen_ArrayRemoveDuplicates; if (count _cleanUnitsArray == 0) then { Zen_Task_Array_Global set [_forEachIndex, 0]; } else { _x set [1, _cleanUnitsArray]; }; } forEach Zen_Task_Array_Global; Zen_Task_Array_Global = Zen_Task_Array_Global - [0]; publicVariable "Zen_Task_Array_Global"; if (true) exitWith {}; The change is on line 12 of the file, in which is previously replaced the entire task data with just the objects that had the task. It now correctly updates the second element of the task data to remove duplicate objects. I had also forgotten the private statement. For now, you can just copy that into the file and it should work fine (I actually tested it this time). It also removes duplicates correctly now. It's really too late to make a full release this Wednesday; a lot of changes are work-in-progress, let alone tested. Hopefully, anyone else with this problem in the next week (that function is used elsewhere in the task system) will see this and copy the new code. Ironically, that change was designed to handle JIP better by remove duplicate objects that might be introduced with repeated JIP players. The point was to make sure mission makers didn't have to worry about players joining, leaving, and joining multiple times for the same player slot when the object name would be the same. -
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
Good to hear, your thanks is much appreciated. At the very top of the init, change the lines that delete the AI to: if !(isMultiplayer) then { { if (_forEachIndex > 0) then { deleteVehicle _x; }; } forEach units player; }; Then add this to the Description.ext: disabledAI = 1; That will make the server to allow those AI to spawn, rather than spawning and deleting them. I don't know if that was the problem, but it is not the typical way of removing AI in MP. Players will be able to JIP and respawn at base normally. If that doesn't work, here are some more things to test: First, do JIP players get all of the tasks, even those that have already been completed, regardless of when they join? Their tasks should be fully synch'd as soon as they join. Those tasks should mirror those of their team leader. Do JIP players continue to get new tasks that are assigned? This will make sure that the array of players is being updated properly, so new JIP players are included in future tasks, considered when spawning zones, etc. Does completing an objective update the task for non-JIP players? Players that joined at the start of the mission shouldn't be affect by JIP players. The objective completion threads run on the server and broadcast the task changes to all the clients. Does JIP affect the clearing of zones of enemy in any way? Do they fail to clear when a JIP player is the only one inside? Do they not spawn when only a JIP player is close? Good find, I must have tested that change with argument checking turned off. You can simply keep that second ["STRING"] in there, or turn off argument checking altogether: Zen_Debug_Arguments = false; Disabling the checking of arguments will usually give a noticeable performance boost (possibly more than 30%). I suggest leaving it on while creating and testing a mission, and disable it for a stable release of the mission. -
Overview Greetings fellow Armaholics, by user request I have updated this mission to use my latest framework. There are only two direct changes to the mission. All three map versions have been updated. Changelog 10/16/14 Improved: Insertion helicopter now starts with a reasonable velocity Tweaked: Crash site objective timing
-
Zenophon's ArmA 3 Co-op Mission Making Framework
Zenophon replied to Zenophon's topic in ARMA 3 - MISSION EDITING & SCRIPTING
The limitations are due to the blind copy-paste nature of the preprocessor. It very useful but makes things less user friendly. There are no errors to tell you if something doesn't work and why, beyond generic syntax errors. You can't put expressions into the arguments and have them be evaluated as in a function call. Anything between the commas is just pasted in order into a template. The macro you are using is for spawning around a point (SPP), with a marker you should use SPM: ZEN_FMW_CS_SPM("teste", 1, west) The very abbreviated names are not making using them any easier. As there are more and more macros, even I can't remember what the letters stand for. Next release I think I'm going to expand at least the last few letters into some words. For example, ZEN_FMW_CS_SpawnPatrolMarker instead of ZEN_FMW_CS_SPM. It makes the names longer, but that's not an issue if the macro replaces 5 lines of code. Thank you for hosting my framework. I will add that mirror to the original post. -
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 Lucky release #13 is the first release in the new bi-monthly schedule, and the release for ArmA stable version 1.32, this release contains quite a few fixes and some significant improvements. Zen_ArrayFilterCondition and its macros have been improved so that they actually work. No one seemed to notice. Also, Zen_SpawnAmbientVehicles failed on repeated calls because it was deleting the markers it used. However, Zen_ConfigGetLocations stores the markers to return again later, so they must remain throughout the mission. A note about that was added to the documentation for Zen_ConfigGetLocations Several spawning functions now have a faction parameter. This parameter applies when the functions select a random vehicle based upon a side. The faction is not used when classnames are given directly. The documentation of these functions has been improved to be much clearer about the difference between a side and classnames. Zen_SpawnConvoy can now offer a faction parameter because it dynamically get vehicle classnames to spawn. These have been tested so that in vanilla ArmA 3 they provide nearly the same values as were previous hard-coded. This means that Zen_SpawnConvoy can now spawn any addon vehicles using the same vehicle type logic. Zen_SpawnConvoy can filter for specific vehicles because Zen_ConfigGetVehicleClasses has been massively improved for detecting armed vehicles. All the weapons of the vehicle, for the driver and all the turrets, and compiled and filtered to remove 'false' weapons (flares, smoke, etc.). This leaves only the true weapons that can do damage. Three new macros have been added, two for ordering AI in and out of vehicles. Those are for AI only and will not force players out of a vehicle, nor force a player leader to order his group to board a vehicle. They are the same code used in Zen_OrderInsertion and Zen_OrderExtraction, just made easy to use. ZEN_FMW_ZAF_FNS is just the opposite of ZEN_FMW_ZAF_FS. Zen_OrderExtraction and Zen_OrderInsertion have been changed to remove the feature of keeping a helicopter's engines on while on the ground. This is due to AI pilot's very persistent ability to take off when units receive an order to get in or out. The previous solution suffered from timing and performance issues, and other simply can't override the AI's need to hover. Forcing the engines off slows things down, but works 100% of the time. Finally, all stable branch 1.32 scripting commands have been added to the included Notepad++ language and autocompletion file. I doubt anyone uses it, but you should give it a try if you haven't. It makes things easier and faster. 10/15/14 Roadmap I am going to work on Zen_OrderExtraction and Zen_OrderInsertion getting AI pilot to keep the engines running and land properly. It seems ridiculous that something so simple is so frustrating. If you have any ideas about an effective solution to this, I'd be glad to hear them. I will also add more macros, probably finally getting to arguments for Zen_FindGroundPosition, as there are a lot of possibilities and a lot of tweaking to do. Regarding changing constants and hard-coded values, e.g. for Zen_SpawnVehicleCrew, there is no easy way of doing this that is very user-friendly. Due to the preprocessor not allowing up directory commands (..\), using #include for constants in functions requires the user copy the header file into every subdirectory. Setting up a global array with a lot of values just opens a lot of possibilities of an index being off, users editing the wrong values, removing or adding to the array. Mistakes and errors like those waste a lot of time. Therefore, the simplest solution to changing hard-coded defaults is simply editing the framework code to change things for your mission. It's simpler to just have a few versions of a file for your different missions or addon combinations. Odds are the function won't change for months, since releases are every two weeks, and I only modify about 10-20 functions each time. If you want some help about what to change, I am more than willing to point out where things are in the code. 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_ArrayFilterCondition. This is a rather useful function, because it completely generalizes a common array operation: removing elements that don't pass a check. Since the three macros for this function now work: // Assume _weapons is an array of firearm classnames, pistols, rifles, etc. _handguns = [_weapons, ZEN_FMW_ZAF_FNS("hgun_")] call Zen_ArrayFilterCondition; That makes things easy, but in general you'll have to write your own conditions. The rules for the condition are simple. It must be a code argument; you can use 'compile' to turn a string into code directly in the arguments. It must return a boolean value, anything else will cause the function to print an error. Finally, you can use '_this' as the element currently being evaluated. Also, remember that the condition is being run from out of scope, so local variables cannot be used, but global variables can. You can avoid string operations by using global variables: // Assume some group has just spawned X = leader _group; _nearObjects = [_objects, {((_this distanceSqr X) > 250000)}] call Zen_ArrayFilterCondition; I am using the square of the distance for a slight performance increase, that's actually 500 meters. You can also use string formatting to put in local variables: // Assume _group is some special group _lesserGroups = [_groupsArray, compile format["(count units _this) > %1", count units _group]] call Zen_ArrayFilterCondition; Due to the limitation of string formatting, you cannot simply put the name of any group or object into the string, unless it has a named reference. Otherwise, a value like 'B Alpha 1-1' will be put in, and the code won't run. Types that are always safe are non-reference types, like strings, numbers, etc. In order to put in a string, you need to use single quotes, '', to nest the strings. For example, this is the code for ZEN_FMW_ZAF_FT: (compile format ["((toLower typeName _this) == '%1')", (toLower T)]) The '%1' places T (the given string) into single quotes, giving 'T'. Otherwise, it would simply put in the string without any quotes, making it an identifier. Finally, a technical note on performance: the condition is evaluated as O(n), once for every element of the array. This means that complex conditions will not reduce performance as they will for Zen_ArraySort, which is O(n*log(n)) (on average for a quick sort). 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
Zen_SpawnInfantryGarrison returns a group, so you must convert that to an array of objects: _zenspawn = [<vars>] call Zen_SpawnInfantryGarrison; zeus addCuratorEditableObjects [(units _zenspawn), false];