Piloto_Spyke 14 Posted December 20, 2020 Hello I'm using the "CAR_F" from Arma 3 Samples to try to configure the FFV (Fire From Vehicle). More or less it works but it does not finish going as I want. I want you to not be able to shoot inside and have the same animation as the others who are sitting (Proxy.Cargo01.XX). Once you go out with the "turn in" I want it to stand up and be able to shoot as if you were out of the vehicle. Some references: MyTestAddonPbo: https://drive.google.com/drive/folders/1qv4Nbt2gfjcp5g31MHKcmNPY1pNiWM0m?usp=sharing Reference 1: https://community.bistudio.com/wiki/Arma_3_Cars_Config_Guidelines#Firing_from_vehicles Reference 2: Quote #include "basicdefines_A3.hpp" class DefaultEventhandlers; #include "CfgPatches.hpp" class WeaponFireGun; class WeaponCloudsGun; class WeaponFireMGun; class WeaponCloudsMGun; class CfgVehicles { class Car; class Car_F: Car { class HitPoints /// we want to use hitpoints predefined for all cars { class HitLFWheel; class HitLF2Wheel; class HitRFWheel; class HitRF2Wheel; class HitBody; class HitGlass1; class HitGlass2; class HitGlass3; class HitGlass4; }; class EventHandlers; }; class Car_F2: Car_F { class CargoTurret; class ViewCargo; class NewTurret; class Turrets { class MainTurret: NewTurret { class ViewOptics; class ViewGunner; class Turrets { class CommanderOptics; }; }; }; }; class Test_Car_01_base_F: Car_F2 { model = "\Samples_f\Test_Car_01\Test_Car_01"; /// simple path to model picture = "\A3\Weapons_F\Data\placeholder_co.paa"; /// just some icon in command bar Icon = "\A3\Weapons_F\Data\placeholder_co.paa"; /// icon in map displayName = "Test Car"; /// displayed in Editor hiddenSelections[] = {"camo1"}; ///we want to allow changing the color of this selection terrainCoef = 6.5; /// different surface affects this car more, stick to tarmac turnCoef = 2.5; /// should match the wheel turn radius precision = 10; /// how much freedom has the AI for its internal waypoints - lower number means more precise but slower approach to way brakeDistance = 3.0; /// how many internal waypoints should the AI plan braking in advance acceleration = 15; /// how fast acceleration does the AI think the car has fireResistance = 5; /// lesser protection against fire than tanks armor = 32; /// just some protection against missiles, collisions and explosions cost = 50000; /// how likely is the enemy going to target this vehicle transportMaxBackpacks = 3; /// just some backpacks fit the trunk by default transportSoldier = 3; /// number of cargo except driver /// some values from parent class to show how to set them up wheelDamageRadiusCoef = 0.9; /// for precision tweaking of damaged wheel size wheelDestroyRadiusCoef = 0.4; /// for tweaking of rims size to fit ground maxFordingDepth = 0.5; /// how high water would damage the engine of the car waterResistance = 1; /// if the depth of water is bigger than maxFordingDepth it starts to damage the engine after this time crewCrashProtection = 0.25; /// multiplier of damage to crew of the vehicle => low number means better protection driverLeftHandAnimName = "drivewheel"; /// according to what bone in model of car does hand move driverRightHandAnimName = "drivewheel"; /// beware, non-existent bones may cause game crashes (even if the bones are hidden during play) class TransportItems /// some first aid kits in trunk according to safety regulations { item_xx(FirstAidKit,4); }; class HitPoints: HitPoints { class HitLFWheel: HitLFWheel {armor=0.125; passThrough=0;}; /// it is easier to destroy wheels than hull of the vehicle class HitLF2Wheel: HitLF2Wheel {armor=0.125; passThrough=0;}; class HitRFWheel: HitRFWheel {armor=0.125; passThrough=0;}; class HitRF2Wheel: HitRF2Wheel {armor=0.125; passThrough=0;}; class HitFuel {armor=0.50; material=-1; name="fueltank"; visual=""; passThrough=0.2;}; /// correct points for fuel tank, some of the damage is aFRLied to the whole class HitEngine {armor=0.50; material=-1; name="engine"; visual=""; passThrough=0.2;}; class HitBody: HitBody {name = "body"; visual="camo1"; passThrough=1;}; /// all damage to the hull is aFRLied to total damage class HitGlass1: HitGlass1 {armor=0.25;}; /// it is pretty easy to puncture the glass but not so easy to remove it class HitGlass2: HitGlass2 {armor=0.25;}; class HitGlass3: HitGlass3 {armor=0.25;}; class HitGlass4: HitGlass4 {armor=0.25;}; }; driverAction = driver_offroad01; /// what action is going the driver take inside the vehicle. Non-existent action makes the vehicle inaccessible cargoAction[] = {passenger_low01, passenger_generic01_leanleft, passenger_generic01_foldhands}; /// the same of all the crew getInAction = GetInLow; /// how does driver look while getting in getOutAction = GetOutLow; /// and out cargoGetInAction[] = {"GetInLow"}; /// and the same for the rest, if the array has fewer members than the count of crew, the last one is used for the rest cargoGetOutAction[] = {"GetOutLow"}; /// that means all use the same in this case #include "sounds.hpp" /// sounds are in a separate file to make this one simple #include "pip.hpp" /// PiPs are in a separate file to make this one simple #include "physx.hpp" /// PhysX settings are in a separate file to make this one simple class PlayerSteeringCoefficients /// steering sensitivity configuration { turnIncreaseConst = 0.3; // basic sensitivity value, higher value = faster steering turnIncreaseLinear = 1.0; // higher value means less sensitive steering in higher speed, more sensitive in lower speeds turnIncreaseTime = 1.0; // higher value means smoother steering around the center and more sensitive when the actual steering angle gets closer to the max. steering angle turnDecreaseConst = 5.0; // basic caster effect value, higher value = the faster the wheels align in the direction of travel turnDecreaseLinear = 3.0; // higher value means faster wheel re-centering in higher speed, slower in lower speeds turnDecreaseTime = 0.0; // higher value means stronger caster effect at the max. steering angle and weaker once the wheels are closer to centered position maxTurnHundred = 0.7; // coefficient of the maximum turning angle @ 100km/h; limit goes linearly to the default max. turn. angle @ 0km/h }; /// memory points where do tracks of the wheel appear // front left track, left offset memoryPointTrackFLL = "TrackFLL"; // front left track, right offset memoryPointTrackFLR = "TrackFLR"; // back left track, left offset memoryPointTrackBLL = "TrackBLL"; // back left track, right offset memoryPointTrackBLR = "TrackBLR"; // front right track, left offset memoryPointTrackFRL = "TrackFRL"; // front right track, right offset memoryPointTrackFRR = "TrackFRR"; // back right track, left offset memoryPointTrackBRL = "TrackBRL"; // back right track, right offset memoryPointTrackBRR = "TrackBRR"; class Damage /// damage changes material in specific places (visual in hitPoint) { tex[]={}; mat[]= { "A3\data_f\glass_veh_int.rvmat", /// material mapped in model "A3\data_f\Glass_veh_damage.rvmat", /// changes to this one once damage of the part reaches 0.5 "A3\data_f\Glass_veh_damage.rvmat", /// changes to this one once damage of the part reaches 1 "A3\data_f\glass_veh.rvmat", /// another material "A3\data_f\Glass_veh_damage.rvmat", /// changes into different ones "A3\data_f\Glass_veh_damage.rvmat" }; }; class Exhausts /// specific exhaust effects for the car { class Exhaust1 /// the car has two exhausts - each on one side { position = "exhaust"; /// name of initial memory point direction = "exhaust_dir"; /// name of memory point for exhaust direction effect = "ExhaustsEffect"; /// what particle effect is it going to use }; class Exhaust2 { position = "exhaust2_pos"; direction = "exhaust2_dir"; effect = "ExhaustsEffect"; }; }; class Reflectors /// only front lights are considered to be reflectors to save CPU { class LightCarHeadL01 /// lights on each side consist of two bulbs with different flares { color[] = {1900, 1800, 1700}; /// approximate colour of standard lights ambient[] = {5, 5, 5}; /// nearly a white one position = "LightCarHeadL01"; /// memory point for start of the light and flare direction = "LightCarHeadL01_end"; /// memory point for the light direction hitpoint = "Light_L"; /// point(s) in hitpoint lod for the light (hitPoints are created by engine) selection = "Light_L"; /// selection for artificial glow around the bulb, not much used any more size = 1; /// size of the light point seen from distance innerAngle = 100; /// angle of full light outerAngle = 179; /// angle of some light coneFadeCoef = 10; /// attenuation of light between the above angles intensity = 1; /// strength of the light useFlare = true; /// does the light use flare? dayLight = false; /// switching light off during day saves CPU a lot flareSize = 1.0; /// how big is the flare class Attenuation { start = 1.0; constant = 0; linear = 0; quadratic = 0.25; hardLimitStart = 30; /// it is good to have some limit otherwise the light would shine to infinite distance hardLimitEnd = 60; /// this allows adding more lights into scene }; }; class LightCarHeadL02: LightCarHeadL01 { position = "LightCarHeadL02"; direction = "LightCarHeadL02_end"; FlareSize = 0.5; /// side bulbs aren't that strong }; class LightCarHeadR01: LightCarHeadL01 { position = "LightCarHeadR01"; direction = "LightCarHeadR01_end"; hitpoint = "Light_R"; selection = "Light_R"; }; class LightCarHeadR02: LightCarHeadR01 { position = "LightCarHeadR02"; direction = "LightCarHeadR02_end"; FlareSize = 0.5; }; }; aggregateReflectors[] = {{"LightCarHeadL01", "LightCarHeadL02"}, {"LightCarHeadR01", "LightCarHeadR02"}}; /// aggregating reflectors helps the engine a lot /// it might be even good to aggregate all lights into one source as it is done for most of the cars class EventHandlers: EventHandlers { // (_this select 0): the vehicle // """" Random texture source (pick one from the property textureList[]) // []: randomize the animation sources (accordingly to the property animationList[]) // false: Don't change the mass even if an animation source has a defined mass init="if (local (_this select 0)) then {[(_this select 0), """", [], false] call bis_fnc_initVehicle;};"; }; // Must be kept as fail-safe in case of issue with the function hiddenSelectionsTextures[]={"\A3\Weapons_F\Data\placeholder_co.paa"}; /// we could use any texture to cover the car // Definition of texture sources (skins), used for the VhC (Vehicle customization) // Also, because the Garage uses the VhC, it will make them available from the garage class textureSources { class red // Source class { displayName="Red"; // name displayed, among other, from the garage author=$STR_A3_Bohemia_Interactive; // Author of the skin textures[]=// List of textures, in the same order as the hiddenSelections definition { "#(rgb,8,8,3)color(1,0,0,1)" // This is procedural texture, can be useful to set placeholder }; factions[]=// This source should be available only for these factions { "OPF_F", "OPF_G_F" // Side Opfor }; }; class blue { displayName="BBBBLue"; author=$STR_A3_Bohemia_Interactive; textures[]= { "#(rgb,8,8,3)color(0,0,1,1)" }; factions[]= { "BLU_F", "BLU_G_F" // Side Blufor }; }; class green { displayName="Green"; author=$STR_A3_Bohemia_Interactive; textures[]= { "#(rgb,8,8,3)color(0,1,0,1)" }; factions[]= { "IND_F", "IND_G_F" // Side independent }; }; class yellow { displayName="Yellow power"; author=$STR_A3_Bohemia_Interactive; textures[]= { "#(rgb,8,8,3)color(0,1,0,1)" }; factions[]= { // Guerilla only "BLU_G_F", "OPF_G_F", "IND_G_F" }; }; class white { displayName="White is white"; author="Another name"; textures[]= { "#(rgb,8,8,3)color(1,1,1,1)" }; factions[]= { "CIV_F" // side civilian }; }; class black { displayName="Dark side"; author="Tom_48_97"; textures[]= { "#(rgb,8,8,3)color(0,0,0,1)" }; factions[]= {}; // Should be available for every factions }; }; // [_textureSourceClass1, _probability1, _textureSourceClass2, _probability2, ...] // Default behavior of the VhC is to select one of these sources, with a weighted random textureList[]= { "red", 1, "green", __EVAL(1/3), // You can also use EVAL to evaluate an expression "blue", 1, "black", 1 // You can noticed that the white source is missing, therefore, it won't be part of the random }; class MFD /// Clocks on the car board { class ClockHUD { #include "cfgHUD.hpp" }; }; class Turrets: Turrets { class CargoTurret_01 : CargoTurret //(FFV) Firing From Vehicles { class ViewGunner : ViewCargo {}; //should fix the arseview, hopefully gunnerAction = "vehicle_turnout_2"; memoryPointsGetInGunner = "pos cargo L"; memoryPointsGetInGunnerDir = "pos cargo L dir"; gunnerName = $STR_A3_TURRETS_CARGOTURRET_R2; gunnerCompartments = Compartment1; proxyIndex = 4; isPersonTurret = 1; // this turret is able to fire both when turned in and out gunnerGetInAction = "GetInHigh"; gunnerGetOutAction = "GetOutHigh"; canHideGunner = 1; gunnerInAction = "passenger_apc_generic02"; enabledByAnimationSource = "left_gunner_move"; inGunnerMayFire = 0; outGunnerMayFire = 1; LODTurnedIn = VIEW_DEFAULT_LOD; LODTurnedOut = VIEW_DEFAULT_LOD; // Old view limits inbounce maxElev = 45; // vertical limit for field of view minElev = -5; // vertical limit for field of view maxTurn = 95; // horizontal limit for field of view minTurn = -95; // horizontal limit for field of view class dynamicViewLimits // additional limits according to filled positions { CargoTurret_02[] = { -65, 95 }; // if CargoTurret_02 is filled, this turret cannot turn that much to negative way (limits from -95 to -65 degrees) }; /// New view limits inbounce class TurnIn /// limits for gunner turned in { limitsArrayTop[] = { {33.8208, -93.9616}, {40.8906, 66.5705} }; // points for the upper curve limitsArrayBottom[] = { {-9.4643, -94.5753}, {-8.3683, -67.6867}, {-9.7173, 43.6372}, {-10.1082, 78.9166} }; /// points for the lower curve }; class TurnOut : TurnIn {}; /// turn out uses the same limits as turn in this time }; }; }; // Derivate from the base class class C_Test_Car_01_F: Test_Car_01_base_F /// some class that is going to be visible in editor { scope = 2; /// makes the car visible in editor scopeCurator=2; // scope 2 means it's available in Zeus mode (0 means hidden) crew = "C_man_1"; /// we need someone to fit into the car side = 3; /// civilian car should be on civilian side faction = CIV_F; /// and with civilian faction }; }; Thx for your help, Spyke Share this post Link to post Share on other sites
Piloto_Spyke 14 Posted December 20, 2020 Video of how it works with the abobe code. Reference 3: Share this post Link to post Share on other sites
Piloto_Spyke 14 Posted January 6, 2021 Well finally with some help from the arma 3 discord (reyhard thx) this is what I have: This is the code for a FFV from a BMR600 (4 cargoTurrets with 2 hatches). Quote class CargoTurret_01 : CargoTurret //(FFV) Firing From Vehicles { gunnerAction = "passenger_inside_6_Idle"; // When you are OUT gunnerInAction = "passenger_apc_narrow_generic01"; // When you are IN gunnerCompartments = "Compartment1"; /// gunner is able to switch gunner seats cargoCompartments = "Compartment1"; /// gunner is able to switch cargo seats memoryPointsGetInGunner = "pos cargoTurret"; /// specific memory points to allow choice of position memoryPointsGetInGunnerDir = "pos cargoTurret dir"; /// direction of get in action gunnerName = "Cargo Turret 1 (BL)"; /// name of the position in the Action menu proxyIndex = 5; /// what cargo proxy is used according to index in the model maxElev = 50; /// what is the highest possible elevation of the turret minElev = -15; /// what is the lowest possible elevation of the turret maxTurn = 120; /// what is the left-most possible turn of the turret minTurn = -120; /// what is the right-most possible turn of the turret isPersonTurret = 1; /// enables firing from vehicle functionality ejectDeadGunner = 0; /// seatbelts included //enabledByAnimationSource = "hatchGunnerOffset_1"; /// doesn't work unless the said animation source is 1 (This doesn't work if the vehicle is inherits from CAR_F) animationSourceHatch = "hatchGunnerOffset_1"; showAsCargo = true; minOutElev=-15; maxOutElev=+80; initOutElev=0; minOutTurn=-90; maxOutTurn=+90; initOutTurn=0; maxHorizontalRotSpeed = 1.0; maxVerticalRotSpeed = 1.0; }; class CargoTurret_02 : CargoTurret_01 { gunnerName = "Cargo Turret 2 (BR)"; animationSourceHatch = "hatchGunnerOffset_2"; proxyIndex = 6; }; class CargoTurret_03 : CargoTurret_01 { gunnerName = "Cargo Turret 3 (FL)"; animationSourceHatch = "hatchGunnerOffset_3"; proxyIndex = 7; }; class CargoTurret_04 : CargoTurret_01 { gunnerName = "Cargo Turret 4 (FR)"; animationSourceHatch = "hatchGunnerOffset_4"; proxyIndex = 8; }; This requieres to create an animationSource Quote class AnimationSources { // Turn 180º the player proxy class hatchGunnerOffset_1 { source="user"; animPeriod=0.5; initPhase=0; }; class hatchGunnerOffset_2 { source="user"; animPeriod=0.5; initPhase=0; }; class hatchGunnerOffset_3 { source="user"; animPeriod=0.5; initPhase=0; }; class hatchGunnerOffset_4 { source="user"; animPeriod=0.5; initPhase=0; }; // Hatch Animations class hatchtop1 { source = "user"; animPeriod = 0; initPhase = 0; }; class hatchtop2 { source = "user"; animPeriod = 0; initPhase = 0; }; }; An EventHandler to detect when the player is turnedOut and move the hatch and rotate the player to the correct direction Quote class EventHandlers: DefaultEventhandlers { class Ripper_BMR600_AnimationsFFV // Este script controlará las animaciones de las escotillas (abrir/cerrar compuerta y Girar 180º el proxy) { init="_scr = _this execVM 'ripper_bmr600\scripts\fn_BMR_TurnOutFFV.sqf'"; }; }; And this is the code (fn_BMR_TurnOutFFV.sqf): Quote params[["_veh",objNull]]; if(isNull _veh)exitWith{}; if !(isServer) exitWith {}; while {alive _veh} do { // Open/Close hatches if (isTurnedOut (_veh turretUnit [1]) || isTurnedOut (_veh turretUnit [2])) then { if (_veh animationPhase "hatchtop1" < 1) then { _veh animateSource ["hatchtop1",1]; }; } else { if ((_veh animationPhase "hatchtop1") > 0) then { _veh animateSource ["hatchtop1", 0]; }; }; if (isTurnedOut (_veh turretUnit [3]) || isTurnedOut (_veh turretUnit [4])) then { if (_veh animationPhase "hatchtop2" < 1) then { _veh animateSource ["hatchtop2",1]; }; } else { if ((_veh animationPhase "hatchtop2") > 0) then { _veh animateSource ["hatchtop2", 0]; }; }; // Rotate player if(isTurnedOut (_veh turretUnit [1]))then{_veh animateSource ["hatchGunnerOffset_1",1];}else{_veh animateSource ["hatchGunnerOffset_1",0];}; if(isTurnedOut (_veh turretUnit [2]))then{_veh animateSource ["hatchGunnerOffset_2",1];}else{_veh animateSource ["hatchGunnerOffset_2",0];}; if(isTurnedOut (_veh turretUnit [3]))then{_veh animateSource ["hatchGunnerOffset_3",1];}else{_veh animateSource ["hatchGunnerOffset_3",0];}; if(isTurnedOut (_veh turretUnit [4]))then{_veh animateSource ["hatchGunnerOffset_4",1];}else{_veh animateSource ["hatchGunnerOffset_4",0];}; sleep 0.5; }; And this the model.cfg Quote class Animations { class hatchGunnerOffset_1 { type="rotationY"; source="user"; // The controller that provides input above selection="cargoTurret_01"; // The name of the skeleton bone used. axis="cargoTurret_01_Axis"; // name of the axis in the model. memory = true; minValue = 0; maxValue = 1; angle0 = "(rad 0)"; angle1 = "(rad 180)"; }; class hatchGunnerOffset_2 : hatchGunnerOffset_1 { selection="cargoTurret_02"; axis="cargoTurret_02_Axis"; }; class hatchGunnerOffset_3 : hatchGunnerOffset_1 { selection="cargoTurret_03"; axis="cargoTurret_03_Axis"; }; class hatchGunnerOffset_4 : hatchGunnerOffset_1 { selection="cargoTurret_04"; axis="cargoTurret_04_Axis"; }; class hatchTop1 { type="rotation"; source="user"; selection="hatchtop1"; axis="hatchtop1_axis"; animPeriod=0; minValue="0"; maxValue="1"; angle0="rad 0"; angle1="rad -170"; memory=1; }; class hatchTop2: hatchTop1 { selection="hatchtop2"; axis="hatchtop2_axis"; }; }; Hope this helps. 2 Share this post Link to post Share on other sites