Jump to content
Zenophon

Zenophon's ArmA 3 Co-op Mission Making Framework

Recommended Posts

Hi Zenophon,

first off, great update! I've been trying out the new additions and i'm not quite certain I understand how to use the caching system correctly, for example the following seems to give me errors;

_pGarrison = [];
_pos = "mkPos1";
_pSpawnPos = getMarkerPos "mkPos1";

for "_i" from 1 to 2 do {
	_pGarrIn = [_pSpawnPos, resistance,"SOF",4,"LOP_Men","LOP_AM",[],"LOP_LeightsOPFOR"] call Zen_SpawnInfantry;
	_pGarrison pushBack _pGarrIn;
	0 = [_pGarrIn,_pos,[],[0,360],"normal","aware",false,true] spawn Zen_OrderInfantryPatrol;
}; 
sleep 2;

_cache = [resistance,"test"] call Zen_Cache;
sleep 1;
_cached = ["test"] call Zen_IsCached;

hint str _cached;

is this the correct way to use this new function? They patrol around a 20m area, but once the error pops up they all run off into the far distance, with no units cached. Same as below,

 

 

Also this throws up the error "unidentified cache identifier";

_cache = [resistance, "test", _pGarrIn] call Zen_Cache;
sleep 1;
_cached = ["test"] call Zen_IsCached;

hint str _cached;

many thanks

Share this post


Link to post
Share on other sites

This is why you are awesome Zen.  You always are willing to help and give out novel solutions.  The dummy unit for assigning tasks should work great for me, since I use a variable that gets set once the mission "starts" and the first tasks are assigned.   Thanks so much for all your hard work!   :bounce3:

Share this post


Link to post
Share on other sites

Hi Zenophon,

first off, great update! I've been trying out the new additions and i'm not quite certain I understand how to use the caching system correctly, for example the following seems to give me errors;

_pGarrison = [];
_pos = "mkPos1";
_pSpawnPos = getMarkerPos "mkPos1";

for "_i" from 1 to 2 do {
	_pGarrIn = [_pSpawnPos, resistance,"SOF",4,"LOP_Men","LOP_AM",[],"LOP_LeightsOPFOR"] call Zen_SpawnInfantry;
	_pGarrison pushBack _pGarrIn;
	0 = [_pGarrIn,_pos,[],[0,360],"normal","aware",false,true] spawn Zen_OrderInfantryPatrol;
}; 
sleep 2;

_cache = [resistance,"test"] call Zen_Cache;
sleep 1;
_cached = ["test"] call Zen_IsCached;

hint str _cached;

is this the correct way to use this new function? They patrol around a 20m area, but once the error pops up they all run off into the far distance, with no units cached. Same as below,

Also this throws up the error "unidentified cache identifier";

_cache = [resistance, "test", _pGarrIn] call Zen_Cache;
sleep 1;
_cached = ["test"] call Zen_IsCached;

hint str _cached;

many thanks

Zen_Cache basically has three modes, which it determines from the pattern of arguments it receives. The first mode is the caching of new units that the system has not cached yet. For this, giving only the units is enough:

_group1 = [player, west, 0, 4] call Zen_SpawnInfantry;

sleep 1;
_id = [_group1] call Zen_Cache;
player commandChat str ([_id] call Zen_IsCached);

sleep 1;
0 = [_id] call Zen_UnCache;
player commandChat str ([_id] call Zen_IsCached);

This code caches _group1 and assigns an identifier to them. The second mode is the caching of units already assigned an identifier; in this mode you need only give the string identifier and Zen_Cache will find the units.

sleep 1;
_id = [_id] call Zen_Cache;
player commandChat str ([_id] call Zen_IsCached);

sleep 1;
0 = [_id] call Zen_UnCache;
player commandChat str ([_id] call Zen_IsCached);

In all cases, Zen_UnCache works like the identifier mode of Zen_Cache; Zen_UnCache cannot create new identifiers. The final mode is an additive mode, in which Zen_Cache adds new units to an existing set of units given by an identifier. This mode requires an existing identifier.

sleep 1;
_group2 = [player, west, 0, 4] call Zen_SpawnInfantry;
_leader2 = leader _group2;

sleep 1;
player commandChat str ([_id] call Zen_GetCachedUnits);
_id = [_group2, _id] call Zen_Cache;
player commandChat str ([_id] call Zen_GetCachedUnits);

sleep 1;
0 = [_id] call Zen_UnCache;

That third example started with _group1 being uncached, but it is not necessary to uncache units assigned to an identifier before adding new units to cache under that identifier. Thus, this is valid:

sleep 1;
_id = [_id] call Zen_Cache;

sleep 1;
_group3 = [player, west, 0, 4] call Zen_SpawnInfantry;

sleep 1;
_id = [_group3, _id] call Zen_Cache;

sleep 1;
0 = [_id] call Zen_UnCache;

Finally, in the additive mode, whether or not the identifier is already cached, you can give a unit or group (be careful giving a group, as caching/uncaching will null old group variables) from the units already assigned to the identifier to join the new units to.

sleep 1;
_group4 = [player, west, 0, 1] call Zen_SpawnInfantry;

sleep 1;
_id = [_group4, _id, _leader2] call Zen_Cache;

sleep 1;
0 = [_id] call Zen_UnCache;

Note that I had to save an object from _group2 (the leader in this case) in order to find that group again. Even when the units previously in _group2 are uncached into a separate group, the new group will not be referred to by _group2.

That was a rather lengthy explanation (and about half of the test script for the cache system), but I wanted to give examples of all the different usages of Zen_Cache. The error it is giving you means that you used the 'additive' mode before using the 'new' mode, and it hasn't been able to create an identifier for those units yet.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks Zen. And you were right. I chose the wrong example Mission to take the JIP-Script from. That one out of your Demonstration is more that what i needed. Thanks for your advice.

Share this post


Link to post
Share on other sites
First of all thanks to Zenophon, I learned a lot of things thanks to him.
 
I tried to change the vehicle classes in "Zen_SpawnAmbientVehicles.sqf" for spawn vehicle from addon :
 

"_carClasses = ["car", independent, "all", "all", "all", "both", _DLC] call Zen_ConfigGetVehicleClasses;
_carObjs = [];"

 
using the config file "Zen_ConfigGetVehicleClasses.sqf" but it doesn’t work. Maybe it’s not the right way to do it?:
 

ZEN_STD_Parse_GetArgumentDefault(_classType, 0, "All")
_side = "all";
_subType = "all";
_faction = "all";
_parents = ["all"];
_weaponState = "both";
_dlcType = "All";
_sideString = "#";

 
I tried a lot of different ways but I don’t understand how to choose the vehicle I want to spawn. Is it possible to do it directly with the classname?
Thanks!
 

Share this post


Link to post
Share on other sites

First of all thanks to Zenophon, I learned a lot of things thanks to him.

I tried to change the vehicle classes in "Zen_SpawnAmbientVehicles.sqf" for spawn vehicle from addon :

"_carClasses = ["car", independent, "all", "all", "all", "both", _DLC] call Zen_ConfigGetVehicleClasses;

_carObjs = [];"

using the config file "Zen_ConfigGetVehicleClasses.sqf" but it doesn’t work. Maybe it’s not the right way to do it?:

ZEN_STD_Parse_GetArgumentDefault(_classType, 0, "All")

_side = "all";

_subType = "all";

_faction = "all";

_parents = ["all"];

_weaponState = "both";

_dlcType = "All";

_sideString = "#";

I tried a lot of different ways but I don’t understand how to choose the vehicle I want to spawn. Is it possible to do it directly with the classname?

Thanks!

I can see how someone might want to spawn specific type of vehicles with the placement Zen_SpawnAmbientVehicles uses. I added the DLC a parameter primarily so that the DLC karts would not appear by default.

In order to avoid having to give Zen_SpawnAmbientVehicles all the arguments to Zen_ConfigGetVehicleClasses, it's a quick change to allow for a list of classnames to be given rather the DLC (which will still be supported). Since it'll be a week or two for the next framework release, I'll just give the new code for that function and you can copy-paste it over the old one. Here's the new function:

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

#include "..\Zen_FrameworkLibrary.sqf"
#include "..\Zen_StandardLibrary.sqf"

_Zen_stack_Trace = ["Zen_SpawnAmbientVehicles", _this] call Zen_StackAdd;
private ["_center", "_distance", "_numCarsRange", "_townMarkers", "_carPos", "_carType", "_car", "_carClasses", "_carsMin", "_carsMax", "_numCars", "_carObjs", "_roadDir", "_customClasses"];

if !([_this, [["VOID"], ["SCALAR"], ["ARRAY", "SCALAR"], ["STRING", "ARRAY"]], [[], [], ["SCALAR"], ["STRING"]], 3] call Zen_CheckArguments) exitWith {
    call Zen_StackRemove;
    ([])
};

_center = [(_this select 0)] call Zen_ConvertToPosition;
_distance = _this select 1;
_numCarsRange = _this select 2;

ZEN_STD_Parse_GetArgumentDefault(_customClasses, 3, "")

_townMarkers = [["NameVillage", "NameCity", "NameCityCapital"]] call Zen_ConfigGetLocations;
_townMarkers = [_townMarkers, (compile format ["(getMarkerPos _this) distance %1", _center]), "hash"] call Zen_ArraySort;

if (typeName _numCarsRange != "ARRAY") then {
    _numCarsRange = [_numCarsRange, _numCarsRange];
};

_carsMin = _numCarsRange select 0;
_carsMax = _numCarsRange select 1;

if ((typeName _customClasses == "ARRAY") && {({isClass (configFile >> "CfgVehicles" >> _x)} count _customClasses) == (count _customClasses)}) then {
    _carClasses = _customClasses;
} else {
    _carClasses = ["car", civilian, "all", "all", "all", "both", _customClasses] call Zen_ConfigGetVehicleClasses;
};

if (count _carClasses == 0) exitWith {
    ZEN_FMW_Code_ErrorExitValue("Zen_SpawnAmbientVehicles", "No vehicle classnames found to spawn.", [])
};

_carObjs = [];
{
    if (([_x, _center] call Zen_Find2dDistance) > _distance) exitWith {};
    _numCars = [_carsMin, _carsMax, true] call Zen_FindInRange;
    for "_i" from 1 to _numCars do {

        _carPos = [_x, 0, 0, 1, [1, 500]] call Zen_FindGroundPosition;
        _carType = [_carClasses] call Zen_ArrayGetRandom;

        _roadDir = [_carPos] call Zen_FindRoadDirection;

        _car = [[_carPos, 4, _roadDir + 90, "trig"] call Zen_ExtendPosition, _carType, 0, 90 - _roadDir] call Zen_SpawnVehicle;
        _carObjs pushBack _car;
    };
} forEach _townMarkers;

call Zen_StackRemove;
(_carObjs)

and the new accompanying documentation:

Spawns (3) empty vehicles in and around all towns and cities within (2) meters from (1).
Towns and cities are printed on the game map.
Usage: Call
Params: 1. Array, group, object, string, the center
        2. Scalar, the distance
        3. Scalar, the number of cars, or Array:
            1. Scalar, the minimum number of cars
            2. Scalar, the maximum number of cars
    AND
 (opt.) 4. Array or string, DLC type(s), 'All' for all DLC, (default: '')
    OR
 (opt.) 4. Array, a list of classnames to choose from at random, (default: civilian cars)
Return: Array of objects, the spawned cars

As a simple test for the new code, you can stand in a town and run this from the debug console:

0 = [player, 200, 20, ["b_mrap_01_f"]] call Zen_SpawnAmbientVehicles;
Of course, there's no reason that the list of classnames can't be generated by Zen_ConfigGetLocations before calling Zen_SpawnAmbientVehicles. For an overview of all its parameters, see the Random Battle Showcase.

Share this post


Link to post
Share on other sites

Update and Release #45

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 will be on Armaholic soon. Please bring any technical issues or mistakes to my attention, so e.g. people don't download the wrong version etc.

Changelog

An auspicious day; the framework now enters its second year since initial release. There have been 696 changes during those two years, including the changes in this release. The highlights here are waypoint features for the AI caching system as well as several small ease-of-use improvements for the template system.

Zen_Cache now saves all waypoint data and Zen_UnCache restores it. I won't go into detail here, as you can now avail yourself of the new AI caching demonstration, which unremittingly shows every part of the AI caching process. For compatibility, all orders functions now assign real waypoints using addWaypoint rather than using the move command.

Zen_CreateTemplate has received a small but very useful tweak; it saves the simulation state of objects. This is used to disable physics for many small objects that would otherwise appear strangely when Zen_SpawnTemplate was used (e.g. things falling through tables). Zen_RotateAsSet can now rotate objects individually after the set rotation; this is used to rotate spawned templates and maintain their exact appearance. Zen_SpawnGroup places units in a small circle around the point given, this should reduce instances of units being stacked on top of each other or being stuck inside objects when spawned with a template.

By user request, Zen_SpawnAmbientVehicles can be given a list of classname to choose from when spawning vehicles. I already posted that for those who wanted to try it early, and it's now incorporated into this release.

Finally, I noticed that addon buildings that can be placed in the editor (e.g. CUP buildings) are not detected by nearestBuilding. Thus, giving the object name directly Zen_FindBuildingPositions will force it to generate positions for that object (provided it is a building) instead of using nearestBuilding.

7/10/16

  • New Function: Zen_CreateCachedUnitWaypoint
  • New Function: Zen_GetCachedUnitsWaypoints
  • New Function: Zen_SetCachedUnitWaypoint
  • Fixed: Zen_Cache printed some debug
  • Fixed: Zen_Cache assigned west units to the east cache, changing their side
  • Added: Zen_RotateAsSet parameter to rotate individual object or markers to maintain their relative facing from the center
  • Improved: Zen_CreateTemplate stores the enableSimulation state of objects
  • Improved: Zen_FindBuildingPositions uses the object given directly if it is a kind of building
  • Improved: Zen_OrderAircraftPatrol, Zen_OrderBoatPatrol, Zen_OrderHelicopterLand, Zen_OrderInfantryMove, Zen_OrderInfantryPatrol, Zen_OrderVehicleMove, and Zen_OrderVehiclePatrol use addWaypoint to create true waypoints
  • Improved: Zen_SpawnAmbientVehicles can be given a list of classnames to spawn
  • Improved: Zen_SpawnGroup places units in a small spread around the starting point
  • Improved: Zen_SpawnTemplate aligns objects to the terrain
  • Documentation: Added for Zen_CreateCachedUnitWaypoint, Zen_GetCachedUnitsWaypoints, and Zen_SetCachedUnitWaypoint
  • Documentation: Added AI caching demonstration
  • Documentation: Improved for Zen_Cache
  • Documentation: Updated for Zen_SpawnAmbientVehicles
  • Like 1

Share this post


Link to post
Share on other sites

Ooo Snap! been waiting for this release! and its great to see your framework reach its 2nd birthday!

Share this post


Link to post
Share on other sites

Hi Zenophon. I have been playing around with the new cache functions and there doing wonders for my framerate on a large Tanoa mission. I have encountered one problem, often the first call to Zen_Cache will take more than 120 seconds. I have tracked this down to the 2.line below (in Zen_Cache.sqf):

Zen_Cache_Group_Array pushBack (createGroup _x);
_group = [[0,0,0], _x, 0, 1] call Zen_SpawnInfantry;
(units _group) join (Zen_Cache_Group_Array select _forEachIndex);
0 = [(units _group)] call _F_Cache;

I did a quick proof of concept where I changed the _F_SideToIndex into _F_SideToGroup:

//Function used by _F_SideToGroup to create group leader
private _F_CreateDummyGroupLeader = {
  params ["_class","_group"];
  _class createUnit [[0,0,0], _group, "", 0, "COLONEL"];
  [(units _group)] call _F_Cache;
};
_F_SideToGroup = {
  (switch (_this select 0) do {
    case west: {
      if (isNil "WEST_GROUP") then {
        WEST_GROUP = createGroup west;
        ["B_Soldier_02_f", WEST_GROUP] call _F_CreateDummyGroupLeader;
        publicVariable "WEST_GROUP";
      };
      WEST_GROUP;
    };
    case east: {
      if (isNil "EAST_GROUP") then {
        EAST_GROUP = createGroup east;
        ["O_G_Soldier_F", EAST_GROUP] call _F_CreateDummyGroupLeader;
        publicVariable "EAST_GROUP";
      };
      EAST_GROUP;
    };
    case resistance: {
      if (isNil "RESISTENCE_GROUP") then {
        RESISTENCE_GROUP = createGroup east;
        ["I_G_Soldier_F", RESISTENCE_GROUP] call _F_CreateDummyGroupLeader;
        publicVariable "RESISTENCE_GROUP";
      };
      RESISTENCE_GROUP;
    };
    case civilian: {
      if (isNil "CIVILLIAN_GROUP") then {
        CIVILLIAN_GROUP = createGroup east;
        ["C_man_1", CIVILLIAN_GROUP] call _F_CreateDummyGroupLeader;
        publicVariable "CIVILLIAN_GROUP";
      };
      CIVILLIAN_GROUP;
    };
    default {
      (-1)
    }
  })
};

And then just use "_unitsGrouped join ([side _unit] call _F_SideToGroup);" when caching units.

 

Performance of the the initial call to Zen_Cache is significantly improved, the biggest downside is the hard dependency on the class names for each side.

Share this post


Link to post
Share on other sites

The delay is the result of Zen_SpawnInfantry using Zen_ConfigGetVehicleClasses to find a unit of each side (the delay only happens once because Zen_ConfigGetVehicleClasses saves its search results). You are right that this is unnecessary and the classnames can be used directly. In the interest of making as few changes as necessary, the spawning code can just be changed to:

if (count Zen_Cache_Group_Array == 0) then {
    {
        Zen_Cache_Group_Array pushBack (createGroup ([_x] call Zen_GetSide));

        _x createUnit [[0,0,0], (Zen_Cache_Group_Array select _forEachIndex), "", 0, "COLONEL"];
        0 = [(units (Zen_Cache_Group_Array select _forEachIndex))] call _F_Cache;
    } forEach ["B_Soldier_f", "O_Soldier_F", "I_soldier_F", "C_man_polo_1_F"];
    publicVariable "Zen_Cache_Group_Array";
};

Which you can benchmark with:

_group = [player, ["B_Soldier_f"]] call Zen_SpawnGroup;
_sTime = diag_tickTime;
_id = [_group] call Zen_Cache;
_eTime = diag_tickTime;
player sideChat str (_eTime - _sTime);

I get about 0.1 seconds now.

Share this post


Link to post
Share on other sites

Hi Zenophon. I try to make a vehicle respawn (when is destroy) like in Sample mission "Zen_respawnPatrol.Altis".

 

I use this code : 

 

f_VehicleRespawn = {
private ["_vehicle", "_timer", "_startPos", "_code", "_className", "_oldVehicle"];

_vehicle = _this select 0;
_timer = _this select 1;

_startPos = getPosATL _vehicle;
_code = "";

if (count _this > 2) then {
_startPos = [(_this select 2)] call Zen_ConvertToPosition;
};

if (count _this > 3) then {
_code = _this select 3;
};

_oldVehicle = objNull;
_className = typeOf _vehicle;

// main loop to detect death of vehicle
while {true} do {
// can run custom code on respawn
if (_code != "") then {
_vehicle call (missionNamespace getVariable _code);
};

waitUntil {
sleep 5;
(!(alive _vehicle) || !(canMove _vehicle))
};

sleep _timer;

if !(isNull _oldVehicle) then {
deleteVehicle _oldVehicle;
};

sleep 5;

_oldVehicle = _vehicle;
_vehicle = [_startPos, _className, 0, 130] call Zen_SpawnVehicle;
};
};

 

But nothing hapened. Maybe i forget something?

 

Thanks

Share this post


Link to post
Share on other sites

You are sure that the thread is running with the name of the correct vehicle? For a simple test, try placing a vehicle in the editor (named e.g. truck) and using

 

0 = [truck, 5] spawn f_VehicleRespawn;
Also, here's an improved version of the function that places the vehicle back at its exact starting position (in case it was initially placed close to other vehicles).

f_VehicleRespawn = {
    private ["_vehicle", "_timer", "_startPos", "_code", "_className", "_oldVehicle", "_startDir"];

    _vehicle = _this select 0;
    _timer = _this select 1;

    _startPos = getPosATL _vehicle;
    _startDir = getDir _vehicle;
    _code = "";

    if (count _this > 2) then {
        _startPos = [(_this select 2)] call Zen_ConvertToPosition;
    };

    if (count _this > 3) then {
        _code = _this select 3;
    };

    _oldVehicle = objNull;
    _className = typeOf _vehicle;

    while {true} do {
        if (_code != "") then {
            _vehicle call (missionNamespace getVariable _code);
        };

        waitUntil {
            sleep 5;
            (!(alive _vehicle) || !(canMove _vehicle))
        };

        sleep _timer;

        if !(isNull _oldVehicle) then {
            deleteVehicle _oldVehicle;
        };

        sleep 1;

        _oldVehicle = _vehicle;
        _vehicle = [_startPos, _className, 0, _startDir, true] call Zen_SpawnVehicle;
    };
};

Share this post


Link to post
Share on other sites

Thanks for the reply!

 

After many test nothing work, but I comment all my mission code and that worked. I think something is wrong in my init. I go look this.

Share this post


Link to post
Share on other sites

I have a question about Zen_OrderInfantryPatrol.  A mission I have in development contains an alarm system.  At the start of the mission I execute Zen_OrderInfantryPatrol with the groups in limited / safe.  Once the alarm has been raised I set them to normal / combat.  This works for a time, but Zen_OrderInfantryPatrol will eventually override the new setting and return them to limited / safe once they reach their next waypoint.

 

My question: Is there a way to have Zen_OrderInfantryPatrol stop executing once a condition has been met? That would then free me up to reissue the function with the new parameters. or perhaps another way to tackle the problem?

 

Thanks.

Share this post


Link to post
Share on other sites

The spawn command returns a thread that you can stop using terminate. For example:

_thread = [...] spawn Zen_OrderInfantryPatrol;

//...

terminate _thread;
The Multi Thread Management demonstration mission has further information and a full example of doing this. Note that in the case of terminating Zen_OrderInfantryPatrol, the groups will continue to carry out their existing move orders until new ones are issued.

Share this post


Link to post
Share on other sites

Zenophon first of all Thanks a million for all the time you spend creating and maintaining this framework. I am am myself relative new to Arma scripting, but I have a background as a software developer, so after all its "just a matter" of another syntax, other frameworks, and getting up to speed with all the strange quirks in Arma scripting. Looking through your source I have learned a lot, and I'm still learning.

 

Anyway, I am working on a small "present" for you, and in this aspect I need to transform a Compass Direction (0°-360°), an Angle (where 0° is along the flat-terrain, 90° is straight up), and a Velocity (meters per second), into a 3 dimentional velocity-vector. I am guessing I have to use one of the "ZEN_STD_Math_VectXXX" macros defined in "Zen_StandardLibrary.sqf", but I am not 100% sure exactly how (given I have these 3 variables: _direction, _angle, _velocity)?

Share this post


Link to post
Share on other sites

...

Anyway, I am working on a small "present" for you, and in this aspect I need to transform a Compass Direction (0°-360°), an Angle (where 0° is along the flat-terrain, 90° is straight up), and a Velocity (meters per second), into a 3 dimentional velocity-vector. I am guessing I have to use one of the "ZEN_STD_Math_VectXXX" macros defined in "Zen_StandardLibrary.sqf", but I am not 100% sure exactly how (given I have these 3 variables: _direction, _angle, _velocity)?

 

I don't think there is a function which does what I want, so I ended up doing the following:

_direction = [_direction] call Zen_FindTrigAngle;

_initVector = [(_initVel * (cos _elvAng) * (cos _direction)), (_initVel * (cos _elvAng) * (sin _direction)), (_initVel * (sin _elvAng))];

Share this post


Link to post
Share on other sites

A magnitude and 2 angles (i.e. r, theta, phi) would be spherical polar coordinates, for which the macro is ZEN_STD_Math_VectPolarCart. I understand your confusion about the arguments, as there are different conventions not only for what theta/phi stand for and what order they go in but also for how the polar angle is measured. ZEN_STD_Math_VectPolarCart is formatted for an input like:

 

_velPolar = [<magnitude>, <XY plane trig angle>, <angle from the Z axis>];
_velCart = ZEN_STD_Math_VectPolarCart(_velPolar);
where 90 degrees from the Z axis lies in the XY plane and the XY angle is measured from the X axis.

In your case, you are using the opposite polar angle convention (i.e. 90 degrees is parallel to the Z axis), thus swapping cosine and sin on the elevation.

All six of the vector conversion macros should have their documentation improved about what arguments they expect and outputs they give.

Share this post


Link to post
Share on other sites

Hey Zen, I'm not sure if this has already been brought up before:  With the recent changes to the task system, several different icons can be chosen for the task.  Any thoughts on making this an optional argument for the task system?

Share this post


Link to post
Share on other sites

Hey Zen, I'm not sure if this has already been brought up before: With the recent changes to the task system, several different icons can be chosen for the task. Any thoughts on making this an optional argument for the task system?

I can have Zen_InvokeTask etc. support setSimpleTaskType; it will just be an extra optional parameter like the destination.

A note to all: I'm moving somewhat far away in 2 days (I was not certain when I would travel until now) and will not have access to a computer capable of running ArmA for a few weeks. I will continue to answer questions to the best of my ability and in as timely a fashion as possible; however, I won't be able to test things or release framework or mission updates during this time. Thank you for your understanding; things will be back to normal in no more than a month.

  • Like 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×