johnnyboy 3793 Posted May 25, 2016 Here's another script from my Property of Mabunga mission. If you've tried that mission, please rate and comment on Steam. With this script, you can make any object fly in V formation. If you use the bird object ("seagull"), the script will play some duck quacking sounds also. If the object is an air vehicle, it turns engine on. This script is intended for ambience and cutscenes, as the flying objects have no AI. Any object can fly, so if flying goats are your thing...have at it. Warning: This script is currently coded to fly at a single altitude, so if you pass in 50 meters as height, and point the formation at a 100 meter hill, it will fly into the hill. It works fine if you know that limitation and use it accordingly. It could be changed to modify Z velocity based on terrain ahead, but I don't plan on doing that any time soon.How to use:1. In the editor create an arrow marker to be the starting point of formation.2. In a trigger or your init file, place a call to my script. The video demo mission shown above had 5 calls to my script in the init.sqf (2 bird formations and 3 jet formations): dmy = ["seagull", getMarkerPos "mrkDuckStart", markerDir "mrkDuckStart", 300, 10, 25, 20] execvm "Scripts\JBOY_BirdFormation.sqf"; sleep 6; dmy = ["seagull", getMarkerPos "mrkDuckStart_1", markerDir "mrkDuckStart_1", 1000, 25, 20, 20] execvm "Scripts\JBOY_BirdFormation.sqf"; sleep 15; dmy = ["B_Plane_CAS_01_F", getMarkerPos "mrkDuckStart_2", markerDir "mrkDuckStart_2", 7000, 15, 150, 400] execvm "Scripts\JBOY_BirdFormation.sqf"; sleep .2; dmy = ["B_Plane_CAS_01_F", getMarkerPos "mrkDuckStart_2", markerDir "mrkDuckStart_2", 7000, 15, 150, 400] execvm "Scripts\JBOY_BirdFormation.sqf"; sleep .2; dmy = ["B_Plane_CAS_01_F", getMarkerPos "mrkDuckStart_2", markerDir "mrkDuckStart_2", 7000, 15, 150, 400] execvm "Scripts\JBOY_BirdFormation.sqf"; 3. Create a file in your mission directory called "JBOY_BirdFormation.sqf" and put this code in it: ////////////////////////////////////////////////////////// // JBOY_BirdFormation.sqf // By: johnnyboy // dmy = ["seagull", getMarkerPos "mrkDuckStart", 180, 1000, 10, 50 , 20] execvm "Scripts\JBOY_BirdFormation.sqf"; // dmy = [objType, startPosition, Direction, Iterations, BirdCount, FlockHeight, speed] execvm "Scripts\JBOY_BirdFormation.sqf"; // // Creates V formation of flying objects ////////////////////////////////////////////////////////// // ducks fly at 30-50 kph _objType = _this select 0; _startPos = _this select 1; _dir = _this select 2; _iterations = _this select 3; _birdCount = _this select 4; _flockHeight = _this select 5; _speed = _this select 6; //_speed = 20; _xx = 0; _sleepTime = .1; // ************************************************************************** // create leader physics object that we can use setvelocity on // ************************************************************************** _obj = "Land_CanOpener_F" createVehicle [10,10000,0]; _obj setdir _dir; _obj allowdamage false; // ************************************************************************** // create bird leader object // ************************************************************************** _birdLeader = _objType createVehicle [5,5,5]; _obj disableCollisionWith _birdLeader; _birdLeader setDir getDir _obj; _birdLeader attachTo [_obj, [0,0,0]]; // ************************************************************************** // Add all objects created to an array so we can delete them later // ************************************************************************** _objArray = []; _objArray pushBack _obj; _objArray pushBack _birdLeader; sleep 5; // Get dimensions of object _bbr = boundingBoxReal _birdLeader; _p1 = _bbr select 0; _p2 = _bbr select 1; _maxWidth = abs ((_p2 select 0) - (_p1 select 0)); //_maxLength = abs ((_p2 select 1) - (_p1 select 1)); //_maxHeight = abs ((_p2 select 2) - (_p1 select 2)); // turn engine on for air vehicles if (_objType isKindOf "Air") then { player action["EngineOn", _birdLeader]; }; // ************************************************************************** // Create and attach all follower birds, calculating relative positions for V formation. // Relative positions based on width of object. Follower positions randomly tweaked // a little so bird formation is not "too perfect". // ************************************************************************** _offset = _maxWidth + (_maxWidth/10); // space between birds for "_i" from 1 to _birdCount -1 do { _bird = _objType createVehicle [5,5,5]; if (_objType isKindOf "Air") then { player action["EngineOn", _bird]; }; _objArray pushBack _bird; _bird setDir getDir _obj; if ((_i mod 2) == 1) then { // Odd followers to the left _bird attachTo [_obj, [_offset*-1 + (random 10/10),_offset*-1, 0]]; } else { // Even followers to the right _bird attachTo [_obj, [_offset + (random 10/10), _offset*-1, 0]]; _offset = _offset + _maxWidth + (_maxWidth/10); }; }; // ************************************************************************** // Move the birds // ************************************************************************** _obj setpos [_startPos select 0, _startPos select 1, _flockHeight]; while {_xx < _iterations} do { _xx = _xx + 1; //_obj setVectorDirAndUP [[0.728425,0.68065,-0.078186], [0.00150812,0.112526,0.993648]]; _obj setVelocity [_speed * sin(_dir), _speed * cos(_dir), 0]; sleep _sleepTime; if (_objType == "seagull") then { // Ducks quack periodically _rand = floor(random 100); switch ( true ) do { case (_rand < 3): { _birdLeader say3d "quack1" }; case (_rand < 6): { _birdLeader say3d "quack2" }; case (_rand < 9): { _birdLeader say3d "quack3" }; }; }; }; // ************************************************************************** // Delete the birds // ************************************************************************** {deleteVehicle _x;} forEach _objArray; I just grabbed the duck noises off the web. You can comment that code out it you want. If you want the duck sounds, let me know, and I will upload this demo mission so you can pull all the files down. 14 Share this post Link to post Share on other sites
Melody_Mike 130 Posted March 21, 2023 Thank you for this. I am trying to set up ambient flybys of a formation of (bomber) planes, and I was getting rather stuck. This seems exactly what I wished for! Had a follow-up question: at the moment I am 'randomizing' it by setting up 4 different cases of starting positions and directions, and having the script pick one. Did you have any luck on making it properly random? I'm imagining generating positions on the edge of a circle marker, but not quite sure how to implement it. Share this post Link to post Share on other sites
johnnyboy 3793 Posted March 21, 2023 Hwy Mike, I wrote this years ago, and don't recall the details. It was strictly for V formations, and beware the warning in OP that height is fixed, so if you point them at a mountain they will fly into it. So its good for only simple ambient fly bys. Share this post Link to post Share on other sites
Melody_Mike 130 Posted March 21, 2023 Thank you for the reply. 15 hours ago, Melody_Mike said: Did you have any luck on making it properly random? I'm imagining generating positions on the edge of a circle marker, but not quite sure how to implement it. I re-read my message, and must admit it wasn't very clear. Here's a sketch of what I mean: And I guess here's a sketch of code that might do it, to be pasted into initserver: // Get terrain dimensions private _axis = worldSize / 2; private _center = [_axis, _axis , 0]; private _radius = sqrt 2 * _axis; // Create marker _mrkcenter = createMarkerLocal ["MrkDuckCenter", _center]; “MrkDuckCenter” setMarkerShapeLocal “ELLIPSE”; "MrkDuckCenter" setMarkerSizeLocal [_axis, _axis]; "MrkDuckCenter" setMarkerDirLocal _theta; "MrkDuckCenter" setMarkerAlphaLocal 0; // Generate angle private _theta = random 360; // Convert to cartesian private _x = _radius * cos( _theta ); private _y = _radius * sin( _theta ); // Set marker position and direction "mrkDuckStart" setMarkerPos [ _x , _y ]; "mrkDuckStart" setMarkerDir ( _theta - 180 ); // Start script _dmy = ["seagull", getMarkerPos "mrkDuckStart", markerDir "mrkDuckStart", 300, 10, 25, 20] execvm "Scripts\JBOY_BirdFormation.sqf"; There's probably a mistake here. I will have to test this later on my machine. There's also no looping. Either I wrap it into a " [] spawn { while {true} do {} }" code block, or perhaps tie it with a https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#Deleted event handler for the birds. To be continued... Share this post Link to post Share on other sites