Ambu5h

Battle Royale Spawn Aircraft

22 posts in this topic

Hereby i present to you all an idea ive had for well over a year.
Wondered why noone else ever made this, quickly figured out its never as easy as it seems.
Had to keep it on hold for a while, but for now most bugs seem to be worked out.

BATTLE ROYALE SPAWNING FOR EXILE.

What does it do?
It creates an aircraft of choice on server startup. Then has it fly a specific route on cycle. It disables damage to this aircraft.
Players that are in an exile family will get the option to spawn  at "Aircraft". (It has to be families-only due to some AI 'bugs?' when non family members join the plane).
This will place them inside the aircraft with multiple parachutes inside it (different kinds to give them options to chose from).
Players can then decide for themselves when they want to eject from the aircraft.
So they can wait untill they are closest to their base or last location of death.

Options
Change the type of aircraft that should be used to drop off players.
You can set your own route for the aircraft to fly on any map.
Set only 1 waypoint to have the plane circle that specific area. But this kind of beats the purpose of this script, set 2 waypoints to have him fly back and forth.
You can set the speed it should fly on. ("LIMITED", "NORMAL", "FULL")
You can set the type of aircraft and its constant fly height. The height should be well above 800m to prevent AI with AA missiles from locking on and wasting ammo.
Keep the same aproximate height in mind when setting the waypoints.

FILES:
spawncraft.sqf  -  (This script spawns the aircraft and pilot)

Spoiler

diag_log "SPAWN AIRCRAFT LOADING!";
 
if (!isServer) exitWith{};
 
private [
"_wayPoints",
"_side",
"_airCraft",
"_vehicleType",
"_group",
"_height",
"_debug",
"_speed"
];
 
_wayPoints = [
        [2879.42, 12604.6, 900],
        [2333.56, 6964.26, 900],
        [4579.37, 2323.64, 900],
        [11660.4, 3145.45, 900],
        [9910.64, 7165.81, 900],
        [6149.39, 10765.3, 900],
        [14199,   13850.1, 900],
        [7867.51, 14851.2, 900]
];                                                     // Waypoints for spawn craft to fly. (defaults are all over tanoa).
                                                    // Set height close to the desired fly height.
_vehicleType = "Exile_Plane_BlackfishInfantry";        // Type of Aircraft.
_height      = 1000;                                  // 1000 meters such that AI with AA missiles wont start targeting.
_speed       = "NORMAL";                              // "LIMITED", "NORMAL", "FULL"
_debug       = true;                                   // Save log messages into server .RPT
_side          = createCenter resistance;                // Set to same as your players. (usually resistance).
_group          = createGroup _side;
[_wayPoints select 0, 90,_vehicleType, _group] call BIS_fnc_spawnVehicle;

_airCraftSelection = nearestObjects [_wayPoints select 0, ["air"], 100];
_airCraft = _airCraftSelection select 0;

if(!isNull _airCraft) then
{
    if (_debug) then
    {diag_log "SPAWN AIRCRAFT: Aircraft ready for bambies!";};
    
    _airCraft setCombatMode "BLUE";
    _airCraft allowDamage false;
    _airCraft flyInHeight _height;
    _airCraft setUnloadInCombat [false, false];
    
    clearBackpackCargoGlobal _airCraft;
    clearItemCargoGlobal _airCraft;
    clearMagazineCargoGlobal _airCraft;
    clearWeaponCargoGlobal _airCraft;
    
    {
        deleteVehicle _x;
    } forEach crew _airCraft;
    
    _airCraft addBackpackCargoGlobal ["B_Parachute", 3];
    _airCraft addBackpackCargoGlobal ["B_I_Parachute_02_F", 3];
    
    _group    addVehicle _airCraft;
    
    _vehicleRoles = (typeOf _airCraft) call bis_fnc_vehicleRoles;
    {
        _safeSpawn = [_wayPoints select 0, 20, 40, 15, 0, 20, 0] call BIS_fnc_findSafePos;
        _vehicleRole = _x select 0;
        _vehicleSeat = _x select 1;
        
        // Add a pilot
        if(_vehicleRole == "Driver") then
        {
            _units = [_safeSpawn, _side, 1] call BIS_fnc_spawnGroup;
            {
                [_x] joinSilent _group;
                
                _x setCombatMode "BLUE";
                _x setBehaviour "CARELESS";
                _x setName "DropshipDennis";
                                        
                _x disableAI "FSM";
                _x disableAI "ANIM";
                _x disableAI "TARGET";
                _x disableAI "THREAT_PATH";
                _x disableAI "PATHPLAN";
                _x disableAI "WAYPOINT_STOP";
                _x disableAI "COLLISIONAVOID";
                _x disableAI "AUTOTARGET";
                _x disableAI "AUTOCOMBAT";
                _x disableAI "COVER";
                _x disableAI "SUPPRESSION";
                _x allowFleeing 0;
                _x setSkill 1;
                _x allowCrewInImmobile true;

                _x assignAsDriver _airCraft;
                _x moveInDriver _airCraft;
                
                _x allowDamage false;
                
                if (_debug) then
                { diag_log format["SPAWN AIRCRAFT: Added Driver! - Side:%1 - Role:%2 - Vehicle:%3", _side, _vehicleRole, typeOf _airCraft]; };
                
            } forEach units _units;
        };
    } forEach _vehicleRoles;

    // Add all waypoints
    {
        _wp = _group addWaypoint [_x, 0];
        _wp setWaypointType "MOVE";
        _wp setWaypointBehaviour "CARELESS";
        _wp setWaypointspeed _speed;
        _wp setWaypointCompletionRadius 400;
        _wp setWaypointVisible false;
        _wp showWaypoint "NEVER";
        
        if (_debug) then
        { diag_log format["SPAWN AIRCRAFT: Added waypoint %1", _x]; };
        
    }foreach _wayPoints;
    
    // Set first waypoint as cycle position
    _wpcycle = _group addWaypoint [_wayPoints select 0, 0];
    _wpcycle setWaypointType "CYCLE";
    _wpcycle setWaypointBehaviour "CARELESS";
    _wpcycle setWaypointspeed _speed;
    _wpcycle setWaypointCompletionRadius 400;
    _wpcycle setWaypointVisible false;
    _wpcycle showWaypoint "NEVER";
};

waitUntil {    
    if (fuel _airCraft < 0.2) then
    {
        _airCraft setFuel 1;
        
        if (_debug) then
        { diag_log "SPAWN AIRCRAFT: Aircraft refueled!"; };
    };
};


ExileServer_object_player_createBambi.sqf  -  This is where the player gets put into the aircraft when that spawn option is selected.

Spoiler

 /**
 * ExileServer_object_player_createBambi
 *
 * Exile Mod
 * exile.majormittens.co.uk
 * © 2015 Exile Mod Team
 *
 * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
 *
 * MODIFIED BY 4MBU5H.
 * This includes spawnloadouts and spawning from an aircraft.
 * Both can easily be implemented or removed if unnessesairy.
 */
 
private["_sessionID","_requestingPlayer","_spawnLocationMarkerName","_bambiPlayer","_accountData","_direction","_position","_spawnAreaPosition","_spawnAreaRadius","_clanID","_clanData","_clanGroup","_player","_devFriendlyMode","_devs","_parachuteNetID","_spawnType","_parachuteObject"];
_sessionID = _this select 0;
_requestingPlayer = _this select 1;
_spawnLocationMarkerName = _this select 2;
_bambiPlayer = _this select 3;
_accountData = _this select 4;
_direction = random 360;
if ((count ExileSpawnZoneMarkerPositions) isEqualTo 0) then
{
    _position = call ExileClient_util_world_findCoastPosition;
    if ((toLower worldName) isEqualTo "namalsk") then
    {
        while {(_position distance2D [76.4239, 107.141, 0]) < 100} do
        {
            _position = call ExileClient_util_world_findCoastPosition;
        };
    };
}
else
{
    _spawnAreaPosition = getMarkerPos _spawnLocationMarkerName;
    _spawnAreaRadius = getNumber(configFile >> "CfgSettings" >> "BambiSettings" >> "spawnZoneRadius");
    _position = [_spawnAreaPosition, _spawnAreaRadius] call ExileClient_util_math_getRandomPositionInCircle;
    while {surfaceIsWater _position} do
    {
        _position = [_spawnAreaPosition, _spawnAreaRadius] call ExileClient_util_math_getRandomPositionInCircle;
    };
};
_name = name _requestingPlayer;
_clanID = (_accountData select 3);
if !((typeName _clanID) isEqualTo "SCALAR") then
{
    _clanID = -1;
    _clanData = [];
}
else
{
    _clanData = missionNamespace getVariable [format ["ExileServer_clan_%1",_clanID],[]];
    if(isNull (_clanData select 5))then
    {
        _clanGroup = createGroup independent;
        _clanData set [5,_clanGroup];
        _clanGroup setGroupIdGlobal [_clanData select 0];
        missionNameSpace setVariable [format ["ExileServer_clan_%1",_clanID],_clanData];
    }
    else
    {
        _clanGroup = (_clanData select 5);
    };
    [_player] joinSilent _clanGroup;
};
_bambiPlayer setPosATL [_position select 0,_position select 1,0];
_bambiPlayer disableAI "FSM";
_bambiPlayer disableAI "MOVE";
_bambiPlayer disableAI "AUTOTARGET";
_bambiPlayer disableAI "TARGET";
_bambiPlayer disableAI "CHECKVISIBLE";
_bambiPlayer setDir _direction;
_bambiPlayer setName _name;
_bambiPlayer setVariable ["ExileMoney", 0, true];
_bambiPlayer setVariable ["ExileScore", (_accountData select 0)];
_bambiPlayer setVariable ["ExileKills", (_accountData select 1)];
_bambiPlayer setVariable ["ExileDeaths", (_accountData select 2)];
_bambiPlayer setVariable ["ExileClanID", _clanID];
_bambiPlayer setVariable ["ExileClanData", _clanData];
_bambiPlayer setVariable ["ExileHunger", 100];
_bambiPlayer setVariable ["ExileThirst", 100];
_bambiPlayer setVariable ["ExileTemperature", 37];
_bambiPlayer setVariable ["ExileWetness", 0];
_bambiPlayer setVariable ["ExileAlcohol", 0];
_bambiPlayer setVariable ["ExileName", _name];
_bambiPlayer setVariable ["ExileOwnerUID", getPlayerUID _requestingPlayer];
_bambiPlayer setVariable ["ExileIsBambi", true];
_bambiPlayer setVariable ["ExileXM8IsOnline", false, true];
_bambiPlayer setVariable ["ExileLocker", (_accountData select 4), true];
_devFriendlyMode = getNumber (configFile >> "CfgSettings" >> "ServerSettings" >> "devFriendyMode");
if (_devFriendlyMode isEqualTo 1) then
{
    _devs = getArray (configFile >> "CfgSettings" >> "ServerSettings" >> "devs");
    {
        if ((getPlayerUID _requestingPlayer) isEqualTo (_x select 0))exitWith
        {
            if((name _requestingPlayer) isEqualTo (_x select 1))then
            {
                _bambiPlayer setVariable ["ExileMoney", 500000, true];
                _bambiPlayer setVariable ["ExileScore", 100000];
            };
        };
    }
    forEach _devs;
};
_parachuteNetID = "";
if ((getNumber(configFile >> "CfgSettings" >> "BambiSettings" >> "parachuteSpawning")) isEqualTo 1) then
{
    _position set [2, getNumber(configFile >> "CfgSettings" >> "BambiSettings" >> "parachuteDropHeight")];
    if ((getNumber(configFile >> "CfgSettings" >> "BambiSettings" >> "haloJump")) isEqualTo 1) then
    {
        _bambiPlayer addBackpackGlobal "B_Parachute";
        _bambiPlayer setPosATL _position;
        _spawnType = 2;
    }
    else
    {
        _parachuteObject = createVehicle ["Steerable_Parachute_F", _position, [], 0, "CAN_COLLIDE"];
        _parachuteObject setDir _direction;
        _parachuteObject setPosATL _position;
        _parachuteObject enableSimulationGlobal true;
        _parachuteNetID = netId _parachuteObject;
        _spawnType = 1;
    };
}
else
{
    _spawnType = 0;
};

if (_spawnLocationMarkerName == "Aircraft") then
{
    {
        if (!isPlayer _x  &&  name _x == "DropshipDennis") then // If it is only an AI named "DropshipDennis"
        {
            _bambiPlayer allowDamage false;

            _bambiPlayer addBackpackGlobal "B_Parachute";
            vehicle _x setFuel 1;                                                                   // Make sure he doesnt run out. If, atleast, someone dies within the hour.

            diag_log format["SPAWN AIRCRAFT: Player chose for aircraft spawn: %1 - %2", name _bambiPlayer, group _bambiPlayer];
            
            [_bambiPlayer] joinSilent _x;                                                         // Have the player join the AI's team. (This will not affect exile parties/families)
            
            _bambiPlayer assignAsCargo vehicle _x;                                                  // Assign player as cargo
            _bambiPlayer moveInCargo vehicle _x;                                                  // Move player into cargo
            
            vehicle _x setUnloadInCombat [false, false];                                          // Disable the AI from triggering landing procedure.

            _bambiPlayer allowDamage true;
        };
    } foreach allunits;
};

_bambiPlayer addMPEventHandler ["MPKilled", {_this call ExileServer_object_player_event_onMpKilled}];
_bambiPlayer call ExileServer_object_player_database_insert;
_bambiPlayer call ExileServer_object_player_database_update;
[
    _sessionID,
    "createPlayerResponse",
    [
        _bambiPlayer,
        _parachuteNetID,
        str (_accountData select 0),
        (_accountData select 1),
        (_accountData select 2),
        100,
        100,
        0,
        (getNumber (configFile >> "CfgSettings" >> "BambiSettings" >> "protectionDuration")) * 60,
        _clanData,
        _spawnType
    ]
]
call ExileServer_system_network_send_to;
[_sessionID, _bambiPlayer] call ExileServer_system_session_update;
true


ExileClient_gui_selectSpawnLocation_show.sqf  -  This is where the spawn option is added to the spawn location list.

Spoiler

/**
 * ExileClient_gui_selectSpawnLocation_show
 *
 * Exile Mod
 * exile.majormittens.co.uk
 * © 2015 Exile Mod Team
 *
 * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
 */
 
private["_display", "_spawnButton", "_listBox", "_listItemIndex", "_numberOfSpawnPoints", "_randNum", "_randData", "_randomSpawnIndex"];
disableSerialization;
ExileClientSpawnLocationSelectionDone = false;
ExileClientSelectedSpawnLocationMarkerName = "";
createDialog "RscExileSelectSpawnLocationDialog";
waitUntil
{
    _display = findDisplay 24002;
    !isNull _display
};
_spawnButton = _display displayCtrl 24003;
_spawnButton ctrlEnable false;
_display displayAddEventHandler ["KeyDown", "_this call ExileClient_gui_loadingScreen_event_onKeyDown"];
_listBox = _display displayCtrl 24002;
lbClear _listBox;
_numberOfSpawnPoints = 0;
{
    if (getMarkerType _x == "ExileSpawnZone") then
    {
        if (markerText _x == "Aircraft") then
        {
            if (ExileClientLoginHasClanResponse) then                    // If this player is in a clan/family. This has to be done otherwise the AI pilot starts going in circles !!??
            {
                _listItemIndex = _listBox lbAdd (markerText _x);
                _listBox lbSetData [_listItemIndex, _x];
                _numberOfSpawnPoints = _numberOfSpawnPoints + 1;
            };
        }
        else
        {
            _listItemIndex = _listBox lbAdd (markerText _x);
            _listBox lbSetData [_listItemIndex, _x];
            _numberOfSpawnPoints = _numberOfSpawnPoints + 1;                                                        // <--
        };
    };
} forEach allMapMarkers;
_numberOfSpawnPoints = {getMarkerType _x == "ExileSpawnZone"} count allMapMarkers;
if (_numberOfSpawnPoints > 0) then
{
    _randNum = floor(random _numberOfSpawnPoints);
    _randData = lbData [24002,_randNum];
    _randomSpawnIndex = _listBox lbAdd "Random";
    _listBox lbSetData [_randomSpawnIndex, _randData];
};
true


ExileServer_object_player_network_hasPlayerRequest.sqf  -  Create or merge this file if you already have one.

Spoiler

/**
 * ExileServer_object_player_network_hasPlayerRequest
 *
 * Exile Mod
 * exile.majormittens.co.uk
 * © 2015 Exile Mod Team
 *
 * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
 *
 * MODIFIED BY ANDREW (Much thanks, such help, very dude)
 */
 
private["_sessionID", "_player", "_hasAlivePlayer"];
_sessionID = _this select 0;
_player = _sessionID call ExileServer_system_session_getPlayerObject;
try
{
    format ["Dispatching hasPlayerRequest for session '%1'...", _sessionID] call ExileServer_util_log;
    if (isNull _player) then
    {
        throw "Player object is null!";
    };
    _uid = getPlayerUID _player;
    if (isNil "_uid") then
    {
        throw "getPlayerUID returned nil!";
    };
    if (_uid isEqualTo "") then
    {
        throw "getPlayerUID returned an empty string!";
    };
    
    //****
    _playerClan = false;
    _accountData = format["getAccountStats:%1", _uid] call ExileServer_system_database_query_selectSingle;
    _clanID = (_accountData select 3);
   
    if !((typeName _clanID) isEqualTo "SCALAR") then
    {
        _playerClan = false;
    }
    else
    {
        _playerClan = true;
    };
 
    _hasAlivePlayer = format["hasAlivePlayer:%1", _uid] call ExileServer_system_database_query_selectSingleField;
    [_sessionID, "hasPlayerResponse", [_hasAlivePlayer,_playerClan]] call ExileServer_system_network_send_to;
   
    //****
}
catch
{
    "hasPlayerRequest failed!" call ExileServer_util_log;
    _exception call ExileServer_util_log;
};
true


ExileClient_object_player_network_hasPlayerResponse.sqf  -  Create or merge this file if you already have one.

Spoiler

/**
 * ExileClient_object_player_network_hasPlayerResponse
 *
 * Exile Mod
 * exile.majormittens.co.uk
 * © 2015 Exile Mod Team
 *
 * This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
 * To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/.
 */
 
ExileClientLoginHasPlayerResponse = _this select 0;
ExileClientLoginHasClanResponse = _this select 1;
true

 

INSTALLATION:
1. Create all of the files above and place them in your mission file. In a location of your choice.
2. Add an ExileSpawnZone named "Aircraft" in your mission.sqm.

{
	position[] = {8000, 1, 8000};
	name="Aircraft";
	text="Aircraft";
	markerType="ELLIPSE";
	type="ExileSpawnZone";
	colorName="ColorBlack";
	alpha=0;
	fillName="SolidBorder";
	a = 5;  
	b = 5;
	drawBorder=0;
	atlOffset=0;
};

3. In either description.ext or config.cpp of you mission file create or overwrite the following classes:

class CfgNetworkMessages
{	
	class hasPlayerResponse
    {
        module="object_player";
        parameters[]=
        {
            "BOOL",
            "BOOL"
        };
    };
};

4. Goto your config.cpp in your missionfile and add the following custom overwrites:

ExileClient_object_player_network_hasPlayerResponse			 = "<Your-Folder>\ExileClient_object_player_network_hasPlayerResponse.sqf";
ExileServer_object_player_network_hasPlayerRequest			 = "<Your-Folder>\ExileServer_object_player_network_hasPlayerRequest.sqf";
ExileClient_gui_selectSpawnLocation_show				 = "<Your-Folder>\ExileClient_gui_selectSpawnLocation_show.sqf";
ExileServer_object_player_createBambi					 = "<Your-Folder>\ExileServer_object_player_createBambi.sqf";

 5. Go into init.sqf (or create one if you dont have one yet) and add the following line:

[] execVM "<Your-Folder>\spawncraft.sqf";

6. Make sure all your paths and references are correct. If you add your files in a folder inside your missionfile. Make sure your overwrites section is also refering to the proper location.
7. Compile mission file... Start server... Login... Create family... Die... Select Aircraft... Fly around.

SIDE NOTE:
I have been testing this with 2 players at most, trying to get it to break. The families used to be a problem but dont seem to couse any issues anymore (since its disabled for non family players).
However i have not been able to test this in a high population envoirment with multiple families and groups spawning at the same time.
If you have a decent population and want to use this, please send me a PM so i can join and keep an eye out for bugs or issues that i was not able to find myself.

Help request:
The limitation to Family's is due to the AI pilots stopping at their next waypoint if someone is not in a family and gets put into the aircraft. (disableAI "WAYPOINT_STOP"; doesnt help)
This is probably related to the reactions of AI to units with different groups being placed in their vehicle.
What im guessing is that the AI automatically tries to land and unload but disableAI does not have any affect on this what so ever.
If anyone with more experience with AI can help me out with this i might be able to enable the spawn option for any player.


Huge thanks to @Andrew_S90 for helping me out sorting out the network messages needed for fixing the family issue.
I learned something there, that was a good day.



UPDATE - 12 June 2017:
- Fixed issue with players spawning dead in the aircraft. Updated createBambi.sqf
- Fixed plane running out of fuel. Updated spawncraft.sqf

Edited by Ambu5h
  • Like 7

Share this post


Link to post
Share on other sites

If you can get some edits going so it works without all those added mods and remove the XG base respawn I'll approve this.

Share this post


Link to post
Share on other sites
Advertisement
1 hour ago, Ambu5h said:

done and tested.

Brilliant, thank you. It'll help save you a million support issues and stops any breach of privacy with other scripts. :)

Share this post


Link to post
Share on other sites
21 hours ago, Capu said:

Yeah... You did it! :-D Great work!!! Are you now the flying Dutchman?

I do tend to fly high sometimes but that doesnt have anything to do with aircraft im afraid ^.^.

Edited by Ambu5h

Share this post


Link to post
Share on other sites

Nice script, I like it really much.

But detected one problem. During a restartcycle of 3h the plane runs out of fuel, as far as I can see after the first test.

Maybe adding some codesnippet like this one to solve this problem...

    
    _airCraft setCombatMode "BLUE";
    _airCraft allowDamage false;
    _airCraft flyInHeight _height;
    _airCraft setUnloadInCombat [false, false];
    waitUntil {	if (!alive _airCraft) exitWith {}; if (fuel _airCraft < 0.25) then { _airCraft setFuel 1 };};


Will test this tomorrow too, need my bed for now ;-)

Edited by CH!LL3R
typo....
  • Like 1

Share this post


Link to post
Share on other sites
13 hours ago, CH!LL3R said:

Nice script, I like it really much.

But detected one problem. During a restartcycle of 3h the plane runs out of fuel, as far as I can see after the first test.

Maybe adding some codesnippet like this one to solve this problem...


    
    _airCraft setCombatMode "BLUE";
    _airCraft allowDamage false;
    _airCraft flyInHeight _height;
    _airCraft setUnloadInCombat [false, false];
    waitUntil {	if (!alive _airCraft) exitWith {}; if (fuel _airCraft < 0.25) then { _airCraft setFuel 1 };};


Will test this tomorrow too, need my bed for now ;-)

Ahh yes, that was one thing i overlooked.
Im using roaming boats aswell (custom script) and i use another custom script that scrolls through all the AI units and refuel's their vehicles every 30 minutes.
There for i did not have this problem.
Gonna test adding your waituntill function now.

Also i noticed a bug where you sometimes die instantly when being move into the aircraft... need a allowdamage false; -> true; for that aswell.
Update comming in an hour or so. UPDATED!

Edited by Ambu5h

Share this post


Link to post
Share on other sites
Advertisement

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.