Braf_Air2 atualizado
This commit is contained in:
28
braf_air2/braf_fnc/braf_constants.h
Normal file
28
braf_air2/braf_fnc/braf_constants.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#define IGUI_GROUP 170
|
||||
|
||||
// IDCs (seus)
|
||||
#define BRAF_ELEV_ARROW 1901
|
||||
#define BRAF_ELEV_TXT 1902
|
||||
#define BRAF_AZ_ARROW 1903
|
||||
#define BRAF_AZ_TXT 1904
|
||||
#define BRAF_NORTH_ARROW 1905
|
||||
|
||||
// RANGES da régua (fixos do seu pod)
|
||||
#define BRAF_MIN_TURN -180
|
||||
#define BRAF_MAX_TURN 180
|
||||
#define BRAF_MIN_ELEV -120
|
||||
#define BRAF_MAX_ELEV 30
|
||||
|
||||
// ====== CONSTANTES DO TAPE (mesmo conceito do USAF) ======
|
||||
// Azimute (horizontal): X do ponto onde está -180 (início da régua)
|
||||
// e distância total até +180 (largura da régua)
|
||||
#define BRAF_AZ_BEG (0.035 * safeZoneW)
|
||||
#define BRAF_AZ_DIS (0.5375 * safeZoneW)
|
||||
#define BRAF_AZ_NUM_OFFSET (-0.009 * safeZoneW)
|
||||
#define BRAF_AZ_TXT_Y_OFFSET (-0.5 * 0.025 * safeZoneH)
|
||||
|
||||
// Elevação (vertical): Y do ponto onde está +30 (topo) e distância total até -120 (base)
|
||||
// (no USAF eles mapeiam para Y)
|
||||
#define BRAF_EZ_BEG (0.196289 * safeZoneH)
|
||||
#define BRAF_EZ_DIS (0.684570 * safeZoneH)
|
||||
#define BRAF_EZ_NUM_OFFSET (0 * safeZoneH)
|
||||
374
braf_air2/braf_fnc/fn_copilot_eject.sqf
Normal file
374
braf_air2/braf_fnc/fn_copilot_eject.sqf
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
Author: Bravo Zero One development
|
||||
- John_Spartan
|
||||
|
||||
Modified:
|
||||
|
||||
-Rodrigo "Ogrinho" Arantes
|
||||
|
||||
Description:
|
||||
- This function is designed to implement semi-authenthic ejection system on fixed wing 2 seated aircrafts.
|
||||
|
||||
Exucution:
|
||||
- Call the function via user action added to the aircrfat itself.
|
||||
|
||||
class Plane_Eject_UserActionExample
|
||||
{
|
||||
priority = 0.05;
|
||||
shortcut = "Eject";
|
||||
displayName = "$STR_A3_action_eject";
|
||||
condition="player in this && {speed this > 1}";
|
||||
statement="[this] spawn BRAF_fnc_EjectPilot, [this] spawn BRAF_fnc_EjectCopilot";
|
||||
position = "pilotcontrol";
|
||||
radius = 10;
|
||||
onlyforplayer = 1;
|
||||
showWindow = 0;
|
||||
hideOnUse = 1;
|
||||
};
|
||||
|
||||
Requirments:
|
||||
- Compatible aircrfat must have a config definition for all sub-sytems that will be invoked by this function.
|
||||
1. Old legacy ejection must be disabled in aircrfat's cfgVehicles configuration.
|
||||
driverCanEject = 0;
|
||||
gunnerCanEject = 0;
|
||||
cargoCanEject = 0;
|
||||
|
||||
2. Aircrfat must have a set of parameters defined in CfgVehicles subClass (EjectionSystem) for ejection system. Theese parameters will affect the ejection behaviour.
|
||||
example of cfgVehicles subclass definitions;
|
||||
|
||||
class EjectionSystem
|
||||
{
|
||||
EjectionSeatEnabled = 1; //enable advanced ejection system
|
||||
EjectionDual = 1; //currently only single seat aircraft ejectiion supported (to do for latter)
|
||||
EjectionSeatClass = "B_Ejection_Seat_Plane_Fighter_01_F"; //class name of ejector seat to use (separate vehicle/object)
|
||||
CanopyClass = "Plane_Fighter_01_Canopy_F"; //class name of canopy to use (separate vehicle/object)
|
||||
EjectionSeatHideAnim1 = "Front_ejection_seat_hide"; //name of the hide animation that will hide front ejector seat mesh in plane
|
||||
EjectionSeatRailAnim1 = "Front_ejection_seat_motion"; //name of the animation that will be played to start a smooth front ejection motion out of cockpit
|
||||
EjectionSeatHideAnim2 = "Back_ejection_seat_hide"; //name of the hide animation that will hide back ejector seat mesh in plane
|
||||
EjectionSeatRailAnim2 = "Back_ejection_seat_motion"; //name of the animation that will be played to start a smooth back ejection motion out of cockpit
|
||||
CanopyHideAnim = "canopy_hide"; //name of the hide animation that will hide canopy mesh in plane
|
||||
EjectionSeatPos1 = "pos_front_eject"; //position memory point where to attach front ejector seat
|
||||
EjectionSeatPos2 = "pos_back_eject"; //position memory point where to attach back ejector seat
|
||||
CanopyPos = "pos_eject_canopy"; //position memory point where to attach dummy canopy
|
||||
EjectionSoundExt = "Plane_Fighter_01_ejection_ext_sound"; //sound to play when ejection trigered (external)
|
||||
EjectionSoundInt = "Plane_Fighter_01_ejection_in_sound"; //sound to play when ejection trigered (in-ternal)
|
||||
EjectionParachute = "Steerable_Parachute_F"; //class name parachute used in ejection
|
||||
EjectionSeatForce = 50; //ejection seat blast force
|
||||
CanopyForce = 30; //canopy bast force
|
||||
|
||||
};
|
||||
|
||||
3. Aircrfat model must have memory points definig positions where to attach new vehicle ejector seat, new vehicle canopy.
|
||||
4. Aircrfat model (in model cfg & class AnimationSources) must have a set of hide animations defined to hide ejector seat and canopy in model when new seaparate vehicles are spawned.
|
||||
|
||||
In model.cfg
|
||||
|
||||
class CanopyHide
|
||||
{
|
||||
type="hide";
|
||||
source="canopy_hide";
|
||||
selection="canopy";
|
||||
sourceAddress="clamp";
|
||||
minPhase=0;
|
||||
maxPhase=1;
|
||||
minValue=0;
|
||||
maxValue=1;
|
||||
memory=0;
|
||||
hideValue=0.001;
|
||||
unHideValue=-1;
|
||||
};
|
||||
class FrontEjectionSeatHide
|
||||
{
|
||||
type="hide";
|
||||
source="front_ejection_seat_hide";
|
||||
selection="ejection_seat_f";
|
||||
sourceAddress="clamp";
|
||||
minPhase=0;
|
||||
maxPhase=1;
|
||||
minValue=0;
|
||||
maxValue=1;
|
||||
memory=0;
|
||||
hideValue=0.001;
|
||||
unHideValue=-1;
|
||||
};
|
||||
class BackEjectionSeatHide: FrontEjectionSeatHide
|
||||
{
|
||||
source="back_ejection_seat_hide";
|
||||
selection="ejection_seat_b";
|
||||
};
|
||||
|
||||
|
||||
In cfgVehicles >> class AnimationSources
|
||||
class CanopyHide
|
||||
{
|
||||
source = "user";
|
||||
animPeriod = 0.001;
|
||||
initPhase = 0;
|
||||
};
|
||||
class FrontEjectionSeatHide
|
||||
{
|
||||
source = "user";
|
||||
animPeriod = 0.001;
|
||||
initPhase = 0;
|
||||
};
|
||||
class BackEjectionSeatHide
|
||||
{
|
||||
source = "user";
|
||||
animPeriod = 0.001;
|
||||
initPhase = 0;
|
||||
};
|
||||
|
||||
5. Aircrfat model must have an animation for initial ejection stage, where new ejector seat with pilot is pushed gradualy out of cockpit (done to avaoid PhysX colisions and make this feature look good, rathre than spawnig ejetor seat above plane).
|
||||
New ejector seat with pilot will be attached to this animation (via animated meory point).
|
||||
Memory point EjectionSeatPos must be part of this animated selection.
|
||||
|
||||
In model.cfg
|
||||
class FrontEjectionSeatMotion
|
||||
{
|
||||
type="translationY";
|
||||
source="front_ejection_seat_motion";
|
||||
selection="ejection_seat_f";
|
||||
sourceAddress="clamp";
|
||||
minPhase=0;
|
||||
maxPhase=1;
|
||||
minValue=0;
|
||||
maxValue=1;
|
||||
memory=0;
|
||||
offset0=0;
|
||||
offset1=3;
|
||||
};
|
||||
class BackEjectionSeatMotion: FrontEjectionSeatMotion
|
||||
{
|
||||
source="back_ejection_seat_motion";
|
||||
selection="ejection_seat_b";
|
||||
};
|
||||
|
||||
In cfgVehicles >> class AnimationSources
|
||||
|
||||
class front_ejection_seat_motion
|
||||
{
|
||||
source="user";
|
||||
animPeriod=0.25;
|
||||
initPhase=0;
|
||||
};
|
||||
class back_ejection_seat_motion: front_ejection_seat_motion
|
||||
{
|
||||
source="user";
|
||||
animPeriod=0.25;
|
||||
initPhase=0;
|
||||
};
|
||||
|
||||
6. Ejector seat and canopy must be created/defined as separate objects. Can be reused.
|
||||
|
||||
Parameter(s):
|
||||
_this select 0: mode (Scalar)
|
||||
0: plane/object
|
||||
|
||||
other parameters are gathered from configuration files.
|
||||
|
||||
Returns: nothing
|
||||
Result: Pilot and copilot will be ejected from aircraft. Semi-authenthic behaviour.
|
||||
|
||||
*/
|
||||
|
||||
#define DISPOSE_ASSETS if (!isNil{_canopy} && {!isNull _canopy}) then {_canopy setDamage 1;addToRemainsCollector [_canopy]}; if (!isNil{_ejectionSeat} && {!isNull _ejectionSeat}) then {addToRemainsCollector [_ejectionSeat]}
|
||||
//#define DISPOSE_ASSETS if (!isNil{_ejectionSeat} && {!isNull _ejectionSeat}) then {addToRemainsCollector [_ejectionSeat]}
|
||||
|
||||
private _plane = param [0,objNull];
|
||||
|
||||
if (isNull _plane || {!alive _plane || {unitIsUAV _plane || {speed _plane < 1}}}) exitWith {};
|
||||
|
||||
if (_plane getVariable ["braf_copilot_ejected",false]) exitWith {};
|
||||
_plane setVariable ["braf_copilot_ejected",true];
|
||||
|
||||
_plane spawn
|
||||
{
|
||||
private _plane = _this;
|
||||
private _copilot = _plane turretUnit[0];
|
||||
|
||||
private _fnc_handleEjectionSeat =
|
||||
{
|
||||
//["[x] Ejection seat '%1' crash tracking initiated! Crew: %2",_this,crew _this] call bis_fnc_logFormat;
|
||||
|
||||
private _timeout = time + 60;
|
||||
|
||||
private _velocity = velocity _this select 2;
|
||||
private _copilot = (crew _this) param [0, objNull];
|
||||
|
||||
//detect crash
|
||||
waitUntil
|
||||
{
|
||||
_velocity = velocity _this select 2;
|
||||
_copilot = (crew _this) param [0, objNull];
|
||||
|
||||
time > _timeout || {(_velocity < 0.05 && {getPos _copilot select 2 < 2})}
|
||||
};
|
||||
|
||||
|
||||
if (time > _timeout) exitWith {};
|
||||
|
||||
//["[x] Ejection seat '%1' with crew %4 crashed to the ground! Delta change: %2 -> %3",_this,_deltaPrev,_delta,crew _this] call bis_fnc_logFormat;
|
||||
|
||||
//lower the velocity to reduce bound effect
|
||||
_this setVelocity (velocity _this apply {_x / 2});
|
||||
|
||||
//kill copilot
|
||||
if (!isNull _copilot) then
|
||||
{
|
||||
moveOut _copilot;
|
||||
_copilot setDamage 1;
|
||||
};
|
||||
|
||||
//destroy the seat so it can be collected by garbage collector
|
||||
_this setDamage 1;
|
||||
};
|
||||
|
||||
if (isNull _plane || {!alive _plane || {isNull _copilot || {!alive _copilot}}}) exitWith {};
|
||||
|
||||
//["[i] Ejecting from plane: %1",_plane] call bis_fnc_logFormat;
|
||||
|
||||
private _configPath = configFile >> "CfgVehicles" >> typeOf _plane >> "EjectionSystem";
|
||||
private _ejectionSeatClass = getText (_configPath >> "EjectionSeatClass");
|
||||
private _ejectionSeatHideAnim = getText (_configPath >> "EjectionSeatHideAnim2");
|
||||
private _ejectionSeatRailAnim = getText (_configPath >> "EjectionSeatRailAnim2");
|
||||
private _ejectionSeatForce = getNumber (_configPath >> "EjectionSeatForce");
|
||||
private _ejectionParachute = getText (_configPath >> "EjectionParachute");
|
||||
private _memoryPointEjectionSeat = getText (_configPath >> "EjectionSeatPos2");
|
||||
|
||||
/*--------------------------------------------------------------------------------------------------
|
||||
|
||||
There is no need to blast off the canopy since it will be done when we call BIS_fnc_planeEjection first.
|
||||
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
sleep 0.25; //to make sure copilot will be ejected 0.5 seconds after canopy and 0.25 seconds before pilot
|
||||
|
||||
/*--------------------------------------------------------------------------------------------------
|
||||
|
||||
Eject the copilot in the ejection seat
|
||||
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
if (isNull _plane || {!alive _plane}) exitWith {DISPOSE_ASSETS};
|
||||
|
||||
//hide ejection seat on plane
|
||||
_plane animate [_ejectionSeatHideAnim,1,true];
|
||||
|
||||
//make pilot invulnerable for the transition time
|
||||
private _wasVulnerable = isDamageAllowed _copilot;
|
||||
|
||||
if (_wasVulnerable) then
|
||||
{
|
||||
_copilot allowDamage false;
|
||||
};
|
||||
|
||||
//create and position ejection seat
|
||||
private _ejectionSeat = createvehicle [_ejectionSeatClass,[0,0,1000],[],0,"CAN_COLLIDE"];
|
||||
|
||||
//_plane disableCollisionWith _ejectionSeat;
|
||||
//_ejectionSeat disableCollisionWith _plane;
|
||||
|
||||
_ejectionSeat attachTo [_plane,[0,0,2],_memoryPointEjectionSeat];
|
||||
|
||||
//move pilot to ejection seat and lock it
|
||||
waitUntil{moveOut _copilot; vehicle _copilot != _plane};
|
||||
waitUntil{_copilot moveInCargo _ejectionSeat; vehicle _copilot == _ejectionSeat};
|
||||
_ejectionSeat lock 2;
|
||||
|
||||
//do rail animation and particle effects
|
||||
_plane animate [_ejectionSeatRailAnim,1];
|
||||
waitUntil{_plane animationPhase _ejectionSeatRailAnim > 0.75};
|
||||
|
||||
detach _ejectionSeat; waitUntil{isNull attachedTo _ejectionSeat};
|
||||
|
||||
//make player once more vulnerable
|
||||
if (_wasVulnerable) then
|
||||
{
|
||||
_copilot allowDamage true;
|
||||
};
|
||||
|
||||
|
||||
[_plane,_ejectionSeat] spawn BIS_fnc_planeEjectionFX;
|
||||
|
||||
//["[x] Ejection seat %1 detached",_ejectionSeat] call bis_fnc_logFormat;
|
||||
|
||||
_planeVelocityModelSpace = velocityModelSpace _plane;
|
||||
_ejectionSeat setVelocityModelSpace (_planeVelocityModelSpace apply {_x/10} vectorAdd [0.5,0.5,_ejectionSeatForce]);
|
||||
|
||||
/*--------------------------------------------------------------------------------------------------
|
||||
|
||||
After ejection
|
||||
- deploy parachute
|
||||
- handle high speed collision with terrain
|
||||
- dispose of canopy and seat
|
||||
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
if (isNull _ejectionSeat) exitWith {DISPOSE_ASSETS};
|
||||
|
||||
private ["_ejectionSeatVelocity"];
|
||||
|
||||
//failsafe for low altitude ejections
|
||||
_ejectionSeat spawn _fnc_handleEjectionSeat;
|
||||
|
||||
//wait for pilot to descend under 350m
|
||||
private _parachuteDeployTime = time + 1;
|
||||
|
||||
waitUntil
|
||||
{
|
||||
_ejectionSeatVelocity = velocity _ejectionSeat;
|
||||
|
||||
!alive _copilot || {!(_copilot in _ejectionSeat) || {(getPos _ejectionSeat select 2 < 350 && {_ejectionSeatVelocity select 2 < -0.5 && {time > _parachuteDeployTime}})}}
|
||||
};
|
||||
|
||||
if (!alive _copilot) exitWith {DISPOSE_ASSETS};
|
||||
|
||||
//move pilot out of the ejection seat
|
||||
if (_copilot in _ejectionSeat) then
|
||||
{
|
||||
_ejectionSeat lock 0;
|
||||
_ejectionSeat setVelocity (_ejectionSeatVelocity apply {_x/4});
|
||||
|
||||
waitUntil
|
||||
{
|
||||
moveOut _copilot;
|
||||
vehicle _copilot != _ejectionSeat
|
||||
};
|
||||
};
|
||||
|
||||
//deploy parachute
|
||||
if (isPlayer _copilot) then
|
||||
{
|
||||
disableUserInput true;
|
||||
};
|
||||
|
||||
private _parachute = createvehicle [_ejectionParachute,getPos _ejectionSeat,[],0,"CAN_COLLIDE"];
|
||||
_parachute setPosWorld (_ejectionSeat modelToWorldWorld [0,0,2.5]);
|
||||
_parachute setDir getDir _ejectionSeat;
|
||||
waitUntil
|
||||
{
|
||||
_copilot moveInDriver _parachute;
|
||||
_copilot in _parachute
|
||||
};
|
||||
if !(_copilot in _parachute) then
|
||||
{
|
||||
_copilot moveInDriver _parachute;
|
||||
};
|
||||
_parachute lock 2;
|
||||
|
||||
sleep 1; //to make sure parachute is locked and player cannot use Get Out ;(
|
||||
|
||||
if (isPlayer _copilot) then
|
||||
{
|
||||
disableUserInput false;
|
||||
};
|
||||
|
||||
//activate achievement
|
||||
setStatValue ["JetsPunchOut", 1];
|
||||
|
||||
//set state of non-funcional assets
|
||||
unassignVehicle _copilot;
|
||||
[_copilot] allowGetIn false;
|
||||
sleep 10;
|
||||
|
||||
//dispose of canopy & ejector seat
|
||||
DISPOSE_ASSETS;
|
||||
};
|
||||
290
braf_air2/braf_fnc/fn_flirControls.sqf
Normal file
290
braf_air2/braf_fnc/fn_flirControls.sqf
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
Author: Brazilian Armed Forces
|
||||
File: fn_flirControls.sqf
|
||||
|
||||
Objetivo:
|
||||
- Atualizar indicadores de AZ (direção) e EZ (elevação) do POD FLIR em relação ao corpo da aeronave
|
||||
- Atualizar indicação de Norte geográfico relativa ao centro do apontamento (compasso)
|
||||
|
||||
Padrão adotado:
|
||||
- Mesmo padrão (carrot/tape):
|
||||
* ler ctrlPosition
|
||||
* calcular posição com BEG/DIS/OFFSET
|
||||
* ctrlSetPosition + ctrlCommit 0
|
||||
|
||||
Observação:
|
||||
- Este script assume que:
|
||||
* os controles estão acessíveis via _display displayCtrl <IDC>
|
||||
* existem constantes BEG/DIS/OFFSET para a régua horizontal (AZ) e vertical (EZ)
|
||||
*/
|
||||
|
||||
#define IGUI_GROUP 170
|
||||
#define BRAF_ELEV_ARROW 1901
|
||||
#define BRAF_ELEV_TXT 1902
|
||||
#define BRAF_AZ_ARROW 1903
|
||||
#define BRAF_AZ_TXT 1904
|
||||
#define BRAF_NORTH_ARROW 1905
|
||||
|
||||
#define BRAF_HDG_VALUE 1907
|
||||
#define BRAF_IAS_VALUE 1909
|
||||
#define BRAF_GS_VALUE 1911
|
||||
#define BRAF_RALT_VALUE 1913
|
||||
#define BRAF_BARO_VALUE 1915
|
||||
#define BRAF_ROLL_VALUE 1917
|
||||
#define BRAF_PTCH_VALUE 1919
|
||||
|
||||
#define BRAF_MIN_TURN -180
|
||||
#define BRAF_MAX_TURN 180
|
||||
#define BRAF_MIN_ELEV -120
|
||||
#define BRAF_MAX_ELEV 30
|
||||
#define BRAF_AZ_BEG (0.04 * safeZoneW)
|
||||
#define BRAF_AZ_DIS (0.5375 * safeZoneW)
|
||||
#define BRAF_AZ_NUM_OFFSET (0.5 * safeZoneW)
|
||||
#define BRAF_AZ_TXT_Y_OFFSET (-1 * 0.025 * safeZoneH)
|
||||
#define BRAF_EZ_BEG (0.215 * safeZoneH)
|
||||
#define BRAF_EZ_DIS (0.52 * safeZoneH)
|
||||
#define BRAF_EZ_NUM_OFFSET (0 * safeZoneH)
|
||||
disableSerialization;
|
||||
|
||||
params ["_display"];
|
||||
|
||||
// Segurança: display inválido
|
||||
if (isNull _display) exitWith {};
|
||||
|
||||
// Segurança: só atualiza quando estiver em optics
|
||||
if (cameraView != "GUNNER") exitWith {};
|
||||
|
||||
// Veículo base (corpo)
|
||||
private _veh = vehicle player;
|
||||
if (isNull _veh) exitWith {};
|
||||
|
||||
// CORREÇÃO: Validar que os controles customizados existem antes de acessá-los
|
||||
// Previne crashes se os IDCs não foram criados corretamente na config
|
||||
if (isNull (_display displayCtrl BRAF_ELEV_ARROW)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle de seta de elevação (IDC 1901) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_AZ_ARROW)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle de seta de azimute (IDC 1903) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_ELEV_TXT)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle de texto de elevação (IDC 1902) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_AZ_TXT)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle de texto de azimute (IDC 1904) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_NORTH_ARROW)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle da bússola norte (IDC 1905) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_HDG_VALUE)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle HDG (IDC 1907) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_IAS_VALUE)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle IAS (IDC 1909) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_GS_VALUE)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle GS (IDC 1911) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_RALT_VALUE)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle RALT (IDC 1913) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_BARO_VALUE)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle BARO (IDC 1915) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_ROLL_VALUE)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle ROLL (IDC 1917) não encontrado!";
|
||||
};
|
||||
if (isNull (_display displayCtrl BRAF_PTCH_VALUE)) exitWith {
|
||||
systemChat "[BRAF A-29] ERRO: Controle PTCH (IDC 1919) não encontrado!";
|
||||
};
|
||||
// ======================================================================
|
||||
// 1) Captura da direção REAL da câmera (mundo) e conversão para o corpo
|
||||
// ======================================================================
|
||||
|
||||
// Vetor forward real da câmera ativa (mundo)
|
||||
private _p0 = positionCameraToWorld [0, 0, 0];
|
||||
private _p1 = positionCameraToWorld [0, 0, 1];
|
||||
private _vW = _p1 vectorDiff _p0;
|
||||
|
||||
private _lenW = vectorMagnitude _vW;
|
||||
if (_lenW < 0.0001) exitWith {};
|
||||
_vW = _vW vectorMultiply (1/_lenW);
|
||||
|
||||
// Direção absoluta (mundo) em RADIANOS para o compasso
|
||||
// atan2 retorna radianos: 0 = norte, π/2 = leste, π ou -π = sul, -π/2 = oeste
|
||||
private _absDir_rad = (_vW select 0) atan2 (_vW select 1);
|
||||
|
||||
// Normalizar para [0, 2π) para ficar positivo
|
||||
if (_absDir_rad < 0) then {
|
||||
_absDir_rad = _absDir_rad + (2 * pi);
|
||||
};
|
||||
|
||||
// Converte vetor para o referencial do veículo (corpo)
|
||||
private _vM = _veh vectorWorldToModel _vW;
|
||||
|
||||
private _lenM = vectorMagnitude _vM;
|
||||
if (_lenM < 0.0001) exitWith {};
|
||||
_vM = _vM vectorMultiply (1/_lenM);
|
||||
|
||||
private _x = _vM select 0;
|
||||
private _y = _vM select 1;
|
||||
private _z = _vM select 2;
|
||||
|
||||
// AZIMUTH (yaw) relativo ao corpo: [-180..+180] em GRAUS
|
||||
private _azimuth = (_x atan2 _y);
|
||||
if (_azimuth > 180) then {
|
||||
_azimuth = _azimuth - 360;
|
||||
};
|
||||
if (_azimuth < -180) then {
|
||||
_azimuth = _azimuth + 360;
|
||||
};
|
||||
|
||||
// ELEVATION (pitch) relativo ao corpo, permitindo < -90 em GRAUS
|
||||
private _h = sqrt (_x*_x + _y*_y);
|
||||
private _signY = if (_y < 0) then {
|
||||
-1
|
||||
} else {
|
||||
1
|
||||
};
|
||||
private _yPrime = _h * _signY;
|
||||
private _elevation = (_z atan2 _yPrime);
|
||||
|
||||
// Clamp nos limites do POD
|
||||
_azimuth = _azimuth max BRAF_MIN_TURN min BRAF_MAX_TURN; // -180..+180
|
||||
_elevation = _elevation max BRAF_MIN_ELEV min BRAF_MAX_ELEV; // -120..+30
|
||||
|
||||
// ======================================================================
|
||||
// 2) TURRET AZ (Azimute/Direção Horizontal)
|
||||
// ======================================================================
|
||||
|
||||
private _turretAZcarrotCtrlPos = ctrlPosition (_display displayCtrl BRAF_AZ_ARROW);
|
||||
private _turretAZtextCtrlPos = ctrlPosition (_display displayCtrl BRAF_AZ_TXT);
|
||||
|
||||
// X do carrot na régua de -180..+180
|
||||
// CORREÇÃO: Referências de constantes alteradas para BRAF_AZ_BEG e BRAF_AZ_DIS
|
||||
private _azPosX = BRAF_AZ_BEG + (((_azimuth + 180) / 360) * BRAF_AZ_DIS);
|
||||
|
||||
// Atualizar posição da seta horizontal (carrot) - IDC 1903
|
||||
(_display displayCtrl BRAF_AZ_ARROW) ctrlSetPosition [
|
||||
_azPosX,
|
||||
_turretAZcarrotCtrlPos select 1,
|
||||
_turretAZcarrotCtrlPos select 2,
|
||||
_turretAZcarrotCtrlPos select 3
|
||||
];
|
||||
(_display displayCtrl BRAF_AZ_ARROW) ctrlCommit 0;
|
||||
|
||||
// Atualizar valor numérico do azimute - IDC 1904
|
||||
// O texto usa o mesmo centro X da seta e fica acima dela.
|
||||
(_display displayCtrl BRAF_AZ_TXT) ctrlSetText str (round _azimuth);
|
||||
|
||||
private _azArrowW = _turretAZcarrotCtrlPos select 2;
|
||||
private _azTextW = _turretAZtextCtrlPos select 2;
|
||||
|
||||
(_display displayCtrl BRAF_AZ_TXT) ctrlSetPosition [
|
||||
_azPosX + ((_azArrowW - _azTextW) / 2),
|
||||
(_turretAZcarrotCtrlPos select 1) + BRAF_AZ_TXT_Y_OFFSET,
|
||||
_azTextW,
|
||||
_turretAZtextCtrlPos select 3
|
||||
];
|
||||
(_display displayCtrl BRAF_AZ_TXT) ctrlCommit 0;
|
||||
|
||||
// ======================================================================
|
||||
// 3) TURRET EZ (Elevação/pitch Vertical)
|
||||
// Régua: +30 (topo) -> -120 (base)
|
||||
// ======================================================================
|
||||
|
||||
private _turretEZcarrotCtrlPos = ctrlPosition (_display displayCtrl BRAF_ELEV_ARROW);
|
||||
private _turretEZtextCtrlPos = ctrlPosition (_display displayCtrl BRAF_ELEV_TXT);
|
||||
|
||||
// tEl: 0 no topo (+30), 1 na base (-120)
|
||||
private _tEl = (BRAF_MAX_ELEV - _elevation) / (BRAF_MAX_ELEV - BRAF_MIN_ELEV);
|
||||
if (_tEl < 0) then {
|
||||
_tEl = 0;
|
||||
};
|
||||
if (_tEl > 1) then {
|
||||
_tEl = 1;
|
||||
};
|
||||
|
||||
// Y da régua
|
||||
// CORREÇÃO: Referências de constantes alteradas para BRAF_EZ_BEG e BRAF_EZ_DIS
|
||||
private _elevPos = BRAF_EZ_BEG + (_tEl * BRAF_EZ_DIS);
|
||||
|
||||
// Atualizar posição da seta vertical (carrot) - IDC 1901
|
||||
(_display displayCtrl BRAF_ELEV_ARROW) ctrlSetPosition [
|
||||
_turretEZcarrotCtrlPos select 0,
|
||||
_elevPos,
|
||||
_turretEZcarrotCtrlPos select 2,
|
||||
_turretEZcarrotCtrlPos select 3
|
||||
];
|
||||
(_display displayCtrl BRAF_ELEV_ARROW) ctrlCommit 0;
|
||||
|
||||
// Atualizar valor numérico da elevação - IDC 1902
|
||||
(_display displayCtrl BRAF_ELEV_TXT) ctrlSetText str (round _elevation);
|
||||
(_display displayCtrl BRAF_ELEV_TXT) ctrlSetPosition [
|
||||
_turretEZtextCtrlPos select 0,
|
||||
_elevPos + BRAF_EZ_NUM_OFFSET,
|
||||
_turretEZtextCtrlPos select 2,
|
||||
_turretEZtextCtrlPos select 3
|
||||
];
|
||||
// CORREÇÃO: Referência de constante alterada para BRAF_EZ_NUM_OFFSET
|
||||
(_display displayCtrl BRAF_ELEV_TXT) ctrlCommit 0;
|
||||
|
||||
// ======================================================================
|
||||
// 4) AIRCRAFT DATA - HDG / IAS / GS / RALT / BARO / ROLL / PTCH
|
||||
// ======================================================================
|
||||
|
||||
private _hdg = round (getDir _veh);
|
||||
private _ias = round (speed _veh);
|
||||
private _gs = round ((vectorMagnitude (velocity _veh)) * 3.6);
|
||||
private _ralt = round ((getPosATL _veh) select 2);
|
||||
private _baro = round ((getPosASL _veh) select 2);
|
||||
|
||||
private _pitchBank = _veh call BIS_fnc_getPitchBank;
|
||||
private _ptch = round (_pitchBank select 0);
|
||||
private _roll = round (_pitchBank select 1);
|
||||
|
||||
private _ctrlHDG = _display displayCtrl BRAF_HDG_VALUE;
|
||||
private _ctrlIAS = _display displayCtrl BRAF_IAS_VALUE;
|
||||
private _ctrlGS = _display displayCtrl BRAF_GS_VALUE;
|
||||
private _ctrlRALT = _display displayCtrl BRAF_RALT_VALUE;
|
||||
private _ctrlBARO = _display displayCtrl BRAF_BARO_VALUE;
|
||||
private _ctrlROLL = _display displayCtrl BRAF_ROLL_VALUE;
|
||||
private _ctrlPTCH = _display displayCtrl BRAF_PTCH_VALUE;
|
||||
|
||||
if (!isNull _ctrlHDG) then {
|
||||
_ctrlHDG ctrlSetText format ["%1", _hdg];
|
||||
};
|
||||
if (!isNull _ctrlIAS) then {
|
||||
_ctrlIAS ctrlSetText format ["%1", _ias];
|
||||
};
|
||||
if (!isNull _ctrlGS) then {
|
||||
_ctrlGS ctrlSetText format ["%1", _gs];
|
||||
};
|
||||
if (!isNull _ctrlRALT) then {
|
||||
_ctrlRALT ctrlSetText format ["%1", _ralt];
|
||||
};
|
||||
if (!isNull _ctrlBARO) then {
|
||||
_ctrlBARO ctrlSetText format ["%1", _baro];
|
||||
};
|
||||
if (!isNull _ctrlROLL) then {
|
||||
_ctrlROLL ctrlSetText format ["%1", _roll];
|
||||
};
|
||||
if (!isNull _ctrlPTCH) then {
|
||||
_ctrlPTCH ctrlSetText format ["%1", _ptch];
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
// 5) COMPASS N (Bússola Norte Geográfico)
|
||||
// ======================================================================
|
||||
|
||||
// CORREÇÃO: Referência de IDC alterada:
|
||||
// COMPASS_N_ARROW → BRAF_NORTH_ARROW (IDC 1905)
|
||||
// Motivo: Alinhar com nomenclatura definida em braf_constants.h
|
||||
//
|
||||
// A fórmula: rotação_seta = -_absDir_rad
|
||||
// Isso faz a seta apontar para o NORTE true em relação ao que a câmera vê:
|
||||
// - Se câmera aponta NORTE: -0° → seta aponta PARA CIMA (norte)
|
||||
// - Se câmera aponta LESTE: -π/2 → seta aponta PARA A ESQUERDA (norte relativo)
|
||||
// - Se câmera aponta SUL: -π → seta aponta PARA BAIXO (norte relativo)
|
||||
// - Se câmera aponta OESTE: -(-π/2) = +π/2 → seta aponta PARA A DIREITA (norte relativo)
|
||||
|
||||
(_display displayCtrl BRAF_NORTH_ARROW) ctrlSetAngle [ -_absDir_rad, 0.5, 0.5 ];
|
||||
48
braf_air2/braf_fnc/fn_initRSC.sqf
Normal file
48
braf_air2/braf_fnc/fn_initRSC.sqf
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Author: Brazilian Armed Forces
|
||||
File: fn_initRSC.sqf
|
||||
|
||||
Objetivo:
|
||||
- Cria e gerencia o loop EachFrame que chama uma função de atualização BRAF_fnc_flirControls
|
||||
|
||||
*/
|
||||
|
||||
disableSerialization;
|
||||
|
||||
params ["_display"];
|
||||
|
||||
// Diagnóstico: Verificar se a função está definida
|
||||
if (isNil "BRAF_fnc_flirControls") then {
|
||||
systemChat "[BRAF A-29] AVISO: BRAF_fnc_flirControls não foi carregada!";
|
||||
};
|
||||
|
||||
uiNamespace setVariable ["BRAF_A29_UI_Display", _display];
|
||||
|
||||
if ((uiNamespace getVariable ["BRAF_A29_PFH_eachFrame", -1]) > -1) then {
|
||||
removeMissionEventHandler ["EachFrame", (uiNamespace getVariable "BRAF_A29_PFH_eachFrame")];
|
||||
uiNamespace setVariable ["BRAF_A29_PFH_eachFrame", nil];
|
||||
};
|
||||
|
||||
private _pfh = addMissionEventHandler ["EachFrame", {
|
||||
if (cameraView != "GUNNER") exitWith {};
|
||||
|
||||
private _display = uiNamespace getVariable ["BRAF_A29_UI_Display", displayNull];
|
||||
|
||||
if (isNull _display) exitWith {
|
||||
removeMissionEventHandler ["EachFrame", (uiNamespace getVariable "BRAF_A29_PFH_eachFrame")];
|
||||
uiNamespace setVariable ["BRAF_A29_PFH_eachFrame", nil];
|
||||
uiNamespace setVariable ["BRAF_A29_UI_Display", nil];
|
||||
};
|
||||
|
||||
private _veh = vehicle player;
|
||||
if (isNull _veh) exitWith {
|
||||
removeMissionEventHandler ["EachFrame", (uiNamespace getVariable "BRAF_A29_PFH_eachFrame")];
|
||||
uiNamespace setVariable ["BRAF_A29_PFH_eachFrame", nil];
|
||||
uiNamespace setVariable ["BRAF_A29_UI_Display", nil];
|
||||
};
|
||||
|
||||
[_display] call BRAF_fnc_flirControls;
|
||||
}];
|
||||
|
||||
uiNamespace setVariable ["BRAF_A29_PFH_eachFrame", _pfh];
|
||||
//systemChat "[BRAF A-29] Sistema FLIR iniciado com sucesso";
|
||||
404
braf_air2/braf_fnc/fn_pilot_eject.sqf
Normal file
404
braf_air2/braf_fnc/fn_pilot_eject.sqf
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
Author: Bravo Zero One development
|
||||
- John_Spartan
|
||||
|
||||
Modified:
|
||||
|
||||
-Rodrigo "Ogrinho" Arantes
|
||||
|
||||
Description:
|
||||
- This function is designed to implement semi-authenthic ejection system on fixed wing 2 seated aircrafts.
|
||||
|
||||
Exucution:
|
||||
- Call the function via user action added to the aircrfat itself.
|
||||
|
||||
class Plane_Eject_UserActionExample
|
||||
{
|
||||
priority = 0.05;
|
||||
shortcut = "Eject";
|
||||
displayName = "$STR_A3_action_eject";
|
||||
condition="player in this && {speed this > 1}";
|
||||
statement="[this] spawn BRAF_fnc_EjectPilot, [this] spawn BRAF_fnc_EjectCopilot";
|
||||
position = "pilotcontrol";
|
||||
radius = 10;
|
||||
onlyforplayer = 1;
|
||||
showWindow = 0;
|
||||
hideOnUse = 1;
|
||||
};
|
||||
|
||||
Requirments:
|
||||
- Compatible aircrfat must have a config definition for all sub-sytems that will be invoked by this function.
|
||||
1. Old legacy ejection must be disabled in aircrfat's cfgVehicles configuration.
|
||||
driverCanEject = 0;
|
||||
gunnerCanEject = 0;
|
||||
cargoCanEject = 0;
|
||||
|
||||
2. Aircrfat must have a set of parameters defined in CfgVehicles subClass (EjectionSystem) for ejection system. Theese parameters will affect the ejection behaviour.
|
||||
example of cfgVehicles subclass definitions;
|
||||
|
||||
class EjectionSystem
|
||||
{
|
||||
EjectionSeatEnabled = 1; //enable advanced ejection system
|
||||
EjectionDual = 1; //currently only single seat aircraft ejectiion supported (to do for latter)
|
||||
EjectionSeatClass = "B_Ejection_Seat_Plane_Fighter_01_F"; //class name of ejector seat to use (separate vehicle/object)
|
||||
CanopyClass = "Plane_Fighter_01_Canopy_F"; //class name of canopy to use (separate vehicle/object)
|
||||
EjectionSeatHideAnim1 = "Front_ejection_seat_hide"; //name of the hide animation that will hide front ejector seat mesh in plane
|
||||
EjectionSeatRailAnim1 = "Front_ejection_seat_motion"; //name of the animation that will be played to start a smooth front ejection motion out of cockpit
|
||||
EjectionSeatHideAnim2 = "Back_ejection_seat_hide"; //name of the hide animation that will hide back ejector seat mesh in plane
|
||||
EjectionSeatRailAnim2 = "Back_ejection_seat_motion"; //name of the animation that will be played to start a smooth back ejection motion out of cockpit
|
||||
CanopyHideAnim = "canopy_hide"; //name of the hide animation that will hide canopy mesh in plane
|
||||
EjectionSeatPos1 = "pos_front_eject"; //position memory point where to attach front ejector seat
|
||||
EjectionSeatPos2 = "pos_back_eject"; //position memory point where to attach back ejector seat
|
||||
CanopyPos = "pos_eject_canopy"; //position memory point where to attach dummy canopy
|
||||
EjectionSoundExt = "Plane_Fighter_01_ejection_ext_sound"; //sound to play when ejection trigered (external)
|
||||
EjectionSoundInt = "Plane_Fighter_01_ejection_in_sound"; //sound to play when ejection trigered (in-ternal)
|
||||
EjectionParachute = "Steerable_Parachute_F"; //class name parachute used in ejection
|
||||
EjectionSeatForce = 50; //ejection seat blast force
|
||||
CanopyForce = 30; //canopy bast force
|
||||
|
||||
};
|
||||
|
||||
3. Aircrfat model must have memory points definig positions where to attach new vehicle ejector seat, new vehicle canopy.
|
||||
4. Aircrfat model (in model cfg & class AnimationSources) must have a set of hide animations defined to hide ejector seat and canopy in model when new seaparate vehicles are spawned.
|
||||
|
||||
In model.cfg
|
||||
|
||||
class CanopyHide
|
||||
{
|
||||
type="hide";
|
||||
source="canopy_hide";
|
||||
selection="canopy";
|
||||
sourceAddress="clamp";
|
||||
minPhase=0;
|
||||
maxPhase=1;
|
||||
minValue=0;
|
||||
maxValue=1;
|
||||
memory=0;
|
||||
hideValue=0.001;
|
||||
unHideValue=-1;
|
||||
};
|
||||
class FrontEjectionSeatHide
|
||||
{
|
||||
type="hide";
|
||||
source="front_ejection_seat_hide";
|
||||
selection="ejection_seat_f";
|
||||
sourceAddress="clamp";
|
||||
minPhase=0;
|
||||
maxPhase=1;
|
||||
minValue=0;
|
||||
maxValue=1;
|
||||
memory=0;
|
||||
hideValue=0.001;
|
||||
unHideValue=-1;
|
||||
};
|
||||
class BackEjectionSeatHide: FrontEjectionSeatHide
|
||||
{
|
||||
source="back_ejection_seat_hide";
|
||||
selection="ejection_seat_b";
|
||||
};
|
||||
|
||||
|
||||
In cfgVehicles >> class AnimationSources
|
||||
class CanopyHide
|
||||
{
|
||||
source = "user";
|
||||
animPeriod = 0.001;
|
||||
initPhase = 0;
|
||||
};
|
||||
class FrontEjectionSeatHide
|
||||
{
|
||||
source = "user";
|
||||
animPeriod = 0.001;
|
||||
initPhase = 0;
|
||||
};
|
||||
class BackEjectionSeatHide
|
||||
{
|
||||
source = "user";
|
||||
animPeriod = 0.001;
|
||||
initPhase = 0;
|
||||
};
|
||||
|
||||
5. Aircrfat model must have an animation for initial ejection stage, where new ejector seat with pilot is pushed gradualy out of cockpit (done to avaoid PhysX colisions and make this feature look good, rathre than spawnig ejetor seat above plane).
|
||||
New ejector seat with pilot will be attached to this animation (via animated meory point).
|
||||
Memory point EjectionSeatPos must be part of this animated selection.
|
||||
|
||||
In model.cfg
|
||||
class FrontEjectionSeatMotion
|
||||
{
|
||||
type="translationY";
|
||||
source="front_ejection_seat_motion";
|
||||
selection="ejection_seat_f";
|
||||
sourceAddress="clamp";
|
||||
minPhase=0;
|
||||
maxPhase=1;
|
||||
minValue=0;
|
||||
maxValue=1;
|
||||
memory=0;
|
||||
offset0=0;
|
||||
offset1=3;
|
||||
};
|
||||
class BackEjectionSeatMotion: FrontEjectionSeatMotion
|
||||
{
|
||||
source="back_ejection_seat_motion";
|
||||
selection="ejection_seat_b";
|
||||
};
|
||||
|
||||
In cfgVehicles >> class AnimationSources
|
||||
|
||||
class front_ejection_seat_motion
|
||||
{
|
||||
source="user";
|
||||
animPeriod=0.25;
|
||||
initPhase=0;
|
||||
};
|
||||
class back_ejection_seat_motion: front_ejection_seat_motion
|
||||
{
|
||||
source="user";
|
||||
animPeriod=0.25;
|
||||
initPhase=0;
|
||||
};
|
||||
|
||||
6. Ejector seat and canopy must be created/defined as separate objects. Can be reused.
|
||||
|
||||
Parameter(s):
|
||||
_this select 0: mode (Scalar)
|
||||
0: plane/object
|
||||
|
||||
other parameters are gathered from configuration files.
|
||||
|
||||
Returns: nothing
|
||||
Result: Pilot and copilot will be ejected from aircraft. Semi-authenthic behaviour.
|
||||
|
||||
*/
|
||||
|
||||
#define DISPOSE_ASSETS if (!isNil{_canopy} && {!isNull _canopy}) then {_canopy setDamage 1;addToRemainsCollector [_canopy]}; if (!isNil{_ejectionSeat} && {!isNull _ejectionSeat}) then {addToRemainsCollector [_ejectionSeat]}
|
||||
//#define DISPOSE_ASSETS if (!isNil{_ejectionSeat} && {!isNull _ejectionSeat}) then {addToRemainsCollector [_ejectionSeat]}
|
||||
|
||||
private _plane = param [0,objNull];
|
||||
|
||||
if (isNull _plane || {!alive _plane || {unitIsUAV _plane || {speed _plane < 1}}}) exitWith {};
|
||||
|
||||
if (_plane getVariable ["braf_pilot_ejected",false]) exitWith {};
|
||||
_plane setVariable ["braf_pilot_ejected",true];
|
||||
|
||||
_plane spawn
|
||||
{
|
||||
private _plane = _this;
|
||||
private _pilot = driver _plane;
|
||||
|
||||
private _fnc_handleEjectionSeat =
|
||||
{
|
||||
//["[x] Ejection seat '%1' crash tracking initiated! Crew: %2",_this,crew _this] call bis_fnc_logFormat;
|
||||
|
||||
private _timeout = time + 60;
|
||||
|
||||
private _velocity = velocity _this select 2;
|
||||
private _pilot = (crew _this) param [0, objNull];
|
||||
|
||||
//detect crash
|
||||
waitUntil
|
||||
{
|
||||
_velocity = velocity _this select 2;
|
||||
_pilot = (crew _this) param [0, objNull];
|
||||
|
||||
time > _timeout || {(_velocity < 0.05 && {getPos _pilot select 2 < 2})}
|
||||
};
|
||||
|
||||
|
||||
if (time > _timeout) exitWith {};
|
||||
|
||||
//["[x] Ejection seat '%1' with crew %4 crashed to the ground! Delta change: %2 -> %3",_this,_deltaPrev,_delta,crew _this] call bis_fnc_logFormat;
|
||||
|
||||
//lower the velocity to reduce bound effect
|
||||
_this setVelocity (velocity _this apply {_x / 2});
|
||||
|
||||
//kill pilot
|
||||
if (!isNull _pilot) then
|
||||
{
|
||||
moveOut _pilot;
|
||||
_pilot setDamage 1;
|
||||
};
|
||||
|
||||
//destroy the seat so it can be collected by garbage collector
|
||||
_this setDamage 1;
|
||||
};
|
||||
|
||||
if (isNull _plane || {!alive _plane || {isNull _pilot || {!alive _pilot}}}) exitWith {};
|
||||
|
||||
//["[i] Ejecting from plane: %1",_plane] call bis_fnc_logFormat;
|
||||
|
||||
private _configPath = configFile >> "CfgVehicles" >> typeOf _plane >> "EjectionSystem";
|
||||
private _ejectionSeatEnabled = getNumber (_configPath >> "EjectionSeatEnabled"); if (_ejectionSeatEnabled == 0) exitWith {};
|
||||
|
||||
private _canopyHideAnim = getText (_configPath >> "CanopyHideAnim"); if (_plane animationPhase _canopyHideAnim > 0.01) exitWith {};
|
||||
private _ejectionSeatClass = getText (_configPath >> "EjectionSeatClass");
|
||||
private _ejectionSeatHideAnim = getText (_configPath >> "EjectionSeatHideAnim");
|
||||
private _ejectionSeatRailAnim = getText (_configPath >> "EjectionSeatRailAnim");
|
||||
private _ejectionSeatForce = getNumber (_configPath >> "EjectionSeatForce");
|
||||
private _canopyForce = getNumber (_configPath >> "canopyForce");
|
||||
private _canopyClass = getText (_configPath >> "canopyClass");
|
||||
private _canopyExplodes = getNumber (_configPath >> "canopyExplodes") == 1;
|
||||
private _ejectionParachute = getText (_configPath >> "EjectionParachute");
|
||||
|
||||
private _memoryPointEjectionSeat = getText (_configPath >> "EjectionSeatPos");
|
||||
private _memoryPointCanopy = getText (_configPath >> "CanopyPos");
|
||||
|
||||
/*--------------------------------------------------------------------------------------------------
|
||||
|
||||
Blast off the canopy first
|
||||
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
//hide canopy on plane
|
||||
_plane animate [_canopyHideAnim,1,true];
|
||||
|
||||
if (!_canopyExplodes) then
|
||||
{
|
||||
//create and position canopy
|
||||
private _canopy = createVehicle [_canopyClass, [100,100,100],[],0,"CAN_COLLIDE"];
|
||||
_canopy allowDamage false;
|
||||
_plane disableCollisionWith _canopy;
|
||||
|
||||
private _canopyPos = _plane modelToWorldWorld ((_plane selectionPosition _memoryPointCanopy) vectorAdd [0,0,2]);
|
||||
_canopy setPosWorld _canopyPos;
|
||||
_canopy setVectorDirAndUp [vectorDir _plane, vectorUp _plane];
|
||||
|
||||
private _planeVelocityModelSpace = velocityModelSpace _plane;
|
||||
_canopy setVelocityModelSpace ((_planeVelocityModelSpace apply {_x/10}) vectorAdd [0,-0.2 * _canopyForce,_canopyForce]);
|
||||
_canopy addTorque (_canopy vectorModelToWorld [-1000,0,0]);
|
||||
};
|
||||
sleep 0.5; //to make sure pilot will be ejected 0.25 seconds after canopy and 0.25 seconds after copilot
|
||||
|
||||
/*--------------------------------------------------------------------------------------------------
|
||||
|
||||
Eject the pilot in the ejection seat
|
||||
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
if (isNull _plane || {!alive _plane}) exitWith {DISPOSE_ASSETS};
|
||||
|
||||
//hide ejection seat on plane
|
||||
_plane animate [_ejectionSeatHideAnim,1,true];
|
||||
|
||||
//make pilot invulnerable for the transition time
|
||||
private _wasVulnerable = isDamageAllowed _pilot;
|
||||
|
||||
if (_wasVulnerable) then
|
||||
{
|
||||
_pilot allowDamage false;
|
||||
};
|
||||
|
||||
//create and position ejection seat
|
||||
private _ejectionSeat = createvehicle [_ejectionSeatClass,[0,0,1000],[],0,"CAN_COLLIDE"];
|
||||
|
||||
//_plane disableCollisionWith _ejectionSeat;
|
||||
//_ejectionSeat disableCollisionWith _plane;
|
||||
|
||||
_ejectionSeat attachTo [_plane,[0,0,2],_memoryPointEjectionSeat];
|
||||
|
||||
//move pilot to ejection seat and lock it
|
||||
waitUntil{moveOut _pilot; vehicle _pilot != _plane};
|
||||
waitUntil{_pilot moveInCargo _ejectionSeat; vehicle _pilot == _ejectionSeat};
|
||||
_ejectionSeat lock 2;
|
||||
|
||||
//["[x] Pilot %1 in ejection seat %2: %3",_pilot,_ejectionSeat,_pilot in _ejectionSeat] call bis_fnc_logFormat;
|
||||
|
||||
//do rail animation and particle effects
|
||||
_plane animate [_ejectionSeatRailAnim,1];
|
||||
waitUntil{_plane animationPhase _ejectionSeatRailAnim > 0.75};
|
||||
|
||||
detach _ejectionSeat; waitUntil{isNull attachedTo _ejectionSeat};
|
||||
|
||||
//make player once more vulnerable
|
||||
if (_wasVulnerable) then
|
||||
{
|
||||
_pilot allowDamage true;
|
||||
};
|
||||
|
||||
|
||||
[_plane,_ejectionSeat] spawn BIS_fnc_planeEjectionFX;
|
||||
|
||||
//["[x] Ejection seat %1 detached",_ejectionSeat] call bis_fnc_logFormat;
|
||||
|
||||
_planeVelocityModelSpace = velocityModelSpace _plane;
|
||||
_ejectionSeat setVelocityModelSpace (_planeVelocityModelSpace apply {_x/10} vectorAdd [0.5,0.5,_ejectionSeatForce]);
|
||||
|
||||
/*--------------------------------------------------------------------------------------------------
|
||||
|
||||
After ejection
|
||||
- deploy parachute
|
||||
- handle high speed collision with terrain
|
||||
- dispose of canopy and seat
|
||||
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
if (isNull _ejectionSeat) exitWith {DISPOSE_ASSETS};
|
||||
|
||||
private ["_ejectionSeatVelocity"];
|
||||
|
||||
//failsafe for low altitude ejections
|
||||
_ejectionSeat spawn _fnc_handleEjectionSeat;
|
||||
|
||||
//wait for pilot to descend under 350m
|
||||
private _parachuteDeployTime = time + 1;
|
||||
|
||||
waitUntil
|
||||
{
|
||||
_ejectionSeatVelocity = velocity _ejectionSeat;
|
||||
|
||||
!alive _pilot || {!(_pilot in _ejectionSeat) || {(getPos _ejectionSeat select 2 < 350 && {_ejectionSeatVelocity select 2 < -0.5 && {time > _parachuteDeployTime}})}}
|
||||
};
|
||||
|
||||
if (!alive _pilot) exitWith {DISPOSE_ASSETS};
|
||||
|
||||
//move pilot out of the ejection seat
|
||||
if (_pilot in _ejectionSeat) then
|
||||
{
|
||||
_ejectionSeat lock 0;
|
||||
_ejectionSeat setVelocity (_ejectionSeatVelocity apply {_x/4});
|
||||
|
||||
waitUntil
|
||||
{
|
||||
moveOut _pilot;
|
||||
vehicle _pilot != _ejectionSeat
|
||||
};
|
||||
};
|
||||
|
||||
//deploy parachute
|
||||
if (isPlayer _pilot) then
|
||||
{
|
||||
disableUserInput true;
|
||||
};
|
||||
|
||||
private _parachute = createvehicle [_ejectionParachute,getPos _ejectionSeat,[],0,"CAN_COLLIDE"];
|
||||
_parachute setPosWorld (_ejectionSeat modelToWorldWorld [0,0,2.5]);
|
||||
_parachute setDir getDir _ejectionSeat;
|
||||
waitUntil
|
||||
{
|
||||
_pilot moveInDriver _parachute;
|
||||
_pilot in _parachute
|
||||
};
|
||||
if !(_pilot in _parachute) then
|
||||
{
|
||||
_pilot moveInDriver _parachute;
|
||||
};
|
||||
_parachute lock 2;
|
||||
|
||||
sleep 1; //to make sure parachute is locked and player cannot use Get Out ;(
|
||||
|
||||
if (isPlayer _pilot) then
|
||||
{
|
||||
disableUserInput false;
|
||||
};
|
||||
|
||||
//activate achievement
|
||||
setStatValue ["JetsPunchOut", 1];
|
||||
|
||||
//set state of non-funcional assets
|
||||
_plane setFuel 0;
|
||||
_plane lock 2;
|
||||
unassignVehicle _pilot;
|
||||
[_pilot] allowGetIn false;
|
||||
sleep 10;
|
||||
|
||||
//dispose of canopy & ejector seat
|
||||
DISPOSE_ASSETS;
|
||||
};
|
||||
83
braf_air2/braf_fnc/fn_remove_before_flight.sqf
Normal file
83
braf_air2/braf_fnc/fn_remove_before_flight.sqf
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Author: Brazilian Armed Forces
|
||||
|
||||
- Rodrigo "Ogrinho" Arantes
|
||||
|
||||
Description:
|
||||
- This function is designed to implement semi-authenthic ejection system on fixed wing 2 seated aircrafts.
|
||||
|
||||
Exucution:
|
||||
- Call the function via user action added to the aircrfat itself.
|
||||
|
||||
class Plane_Eject_UserActionExample
|
||||
{
|
||||
priority = 0.05;
|
||||
shortcut = "Eject";
|
||||
displayName = "$STR_A3_action_eject";
|
||||
condition="player in this && {speed this > 1}";
|
||||
statement="[this] spawn BRAF_fnc_EjectPilot, [this] spawn BRAF_fnc_EjectCopilot";
|
||||
position = "pilotcontrol";
|
||||
radius = 10;
|
||||
onlyforplayer = 1;
|
||||
showWindow = 0;
|
||||
hideOnUse = 1;
|
||||
};
|
||||
|
||||
Requirments:
|
||||
Aircrfat model (in model cfg & class AnimationSources) must have a set of hide animations defined to hide the covers and wheel chocks when new seaparate vehicles are spawned.
|
||||
|
||||
In model.cfg
|
||||
|
||||
class RBFHide
|
||||
{
|
||||
type="hide";
|
||||
source="canopy_hide";
|
||||
selection="rbf";
|
||||
sourceAddress="clamp";
|
||||
minPhase=0;
|
||||
maxPhase=1;
|
||||
minValue=0;
|
||||
maxValue=1;
|
||||
memory=1;
|
||||
hideValue=0.001;
|
||||
};
|
||||
|
||||
In cfgVehicles >> class AnimationSources
|
||||
|
||||
class RBFHide
|
||||
{
|
||||
source = "user";
|
||||
animPeriod = 0.001;
|
||||
initPhase = 0;
|
||||
};
|
||||
|
||||
Parameter(s):
|
||||
_this select 0: mode (Scalar)
|
||||
0: plane/object
|
||||
|
||||
other parameters are gathered from configuration files.
|
||||
|
||||
Returns: nothing
|
||||
Result: Intake, Pitot tube and Propellers covers, wheel chock and another protections will show up. Aircraft will be locked.
|
||||
|
||||
*/
|
||||
|
||||
#define DISPOSE_ASSETS if (!isNil{_canopy} && {!isNull _canopy}) then {_canopy setDamage 1;addToRemainsCollector [_canopy]}; if (!isNil{_ejectionSeat} && {!isNull _ejectionSeat}) then {addToRemainsCollector [_ejectionSeat]}
|
||||
|
||||
private _plane = param [0,objNull];
|
||||
|
||||
if (isNull _plane || {!alive _plane || {unitIsUAV _plane || {speed _plane > 1}}}) exitWith {};
|
||||
|
||||
if (_plane getVariable ["braf_A29_locked",false]) exitWith {};
|
||||
_plane setVariable ["braf_A29_locked",true];
|
||||
|
||||
_plane spawn
|
||||
{
|
||||
private _plane = _this;
|
||||
//hide ejection seat on plane
|
||||
_plane animateSource [RBFHide, 1, true];
|
||||
_plane animateSource [rotor, 0, true];
|
||||
_plane lock 2;
|
||||
|
||||
|
||||
};
|
||||
98
braf_air2/braf_fnc/fn_smoker.sqf
Normal file
98
braf_air2/braf_fnc/fn_smoker.sqf
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
Author: Brazilian Armed Forces
|
||||
-Rodrigo "Ogrinho" Arantes
|
||||
|
||||
Description:
|
||||
- This function is designed to implement smoke ejection from A-29 exhaust
|
||||
|
||||
Exucution:
|
||||
- call the function via user action added to the aircrfat itself.
|
||||
|
||||
to activate smoke emitter:
|
||||
|
||||
class BRAF_Smoke_Toggle
|
||||
{
|
||||
priority=0.05;
|
||||
shortcut="Smoke On";
|
||||
displayName="Fumaça já!";
|
||||
condition="player in this && {
|
||||
speed this > 1
|
||||
}";
|
||||
statement="[this] spawn BRAF_fnc_SmokeOn";
|
||||
position="pilotcontrol";
|
||||
radius=10;
|
||||
onlyforplayer=1;
|
||||
showWindow=0;
|
||||
};
|
||||
|
||||
Requirments:
|
||||
|
||||
- Compatible aircraft must have a config definition for all sub-sytems that will be invoked by this function.
|
||||
|
||||
1- Aircrfat model must have memory a point called "smoker_spawn" definig the position where to attach smoke generator.
|
||||
|
||||
Result: Smoke effect particles will be ejected from aircrafts right exhaustor, and vehicleChat will say "Fumaça Já!"
|
||||
|
||||
*/
|
||||
|
||||
/*--------------------------------------------------------------------------------------------------
|
||||
|
||||
Conditions to play the function:
|
||||
1- Aircraft is alive.
|
||||
2- Aircraft speed > 1.
|
||||
3- "braf_smoke_on" variable == true
|
||||
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
private _plane = param [0, objNull];
|
||||
|
||||
if (isNull _plane ||
|
||||
{
|
||||
!alive _plane ||
|
||||
{
|
||||
speed _plane < 1
|
||||
}
|
||||
}
|
||||
) exitWith {};
|
||||
if (_plane getVariable ["braf_smoke_on", true]) then {
|
||||
/*--------------------------------------------------------------------------------------------------
|
||||
|
||||
Creation of smoke generator and attaching it to vehicle's "smoker_spawn" memory point
|
||||
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
_plane spawn
|
||||
{
|
||||
private _plane = _this;
|
||||
_plane vehicleChat "Fumaça Já!";
|
||||
sleep 0.25;
|
||||
private _smoker = "#particlesource" createVehicleLocal [0, 0, 0];
|
||||
_smoker setParticleParams
|
||||
[
|
||||
["\A3\Data_F\ParticleEffects\Universal\Universal", 16, 7, 16, 1],
|
||||
"", "Billboard", 1, 16, // AnimationName, type, timerPeriod, lifeTime
|
||||
[0, 0, 0], // position relative to referenceObject
|
||||
[0, 0, 0], // velocity
|
||||
0, 10, 7.9, 0.066, [1, 3, 6], // Rotation, Weight, Volume, Rubbing, size
|
||||
[
|
||||
[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 0.75], [1, 1, 1, 0.5], [1, 1, 1, 0.25], [1, 1, 1, 0] // Array for smoke colors [R, G, B, A]
|
||||
],
|
||||
[0.25], // animationPhase
|
||||
1, 0, // randomDerictionPeriod, randomDirectionIntensity
|
||||
"", "", // onTimer, beforeDestroy
|
||||
_smoker// referenceObject
|
||||
];
|
||||
_smoker setParticleRandom [0, [0.25, 0.25, 0], [0.2, 0.2, 0], 0, 0.25, [0, 0, 0, 0.1], 0, 0];
|
||||
_smoker setDropInterval 0.025;
|
||||
_smoker setDir (getDir _plane);
|
||||
_smoker setPosASL (_plane modelToWorld [0, 0, 0]);
|
||||
_smoker attachTo [_plane, [0, 0, 0], "smoker_spawn"];
|
||||
|
||||
_plane setVariable ["smoker", _smoker];
|
||||
_plane setVariable ["braf_smoke_on", false];
|
||||
};
|
||||
} else {
|
||||
private _smoker = _plane GetVariable ["smoker", objNull];
|
||||
deleteVehicle _smoker;
|
||||
_plane vehicleChat "Fumaça Off!";
|
||||
_plane setVariable ["smoker", nil];
|
||||
_plane setVariable ["braf_smoke_on", true];
|
||||
};
|
||||
Reference in New Issue
Block a user