diff --git a/addons/core/functions/fn_endRadioTransmission.sqf b/addons/core/functions/fn_endRadioTransmission.sqf index 2b9d0bd4bf..7cf764b6c5 100644 --- a/addons/core/functions/fn_endRadioTransmission.sqf +++ b/addons/core/functions/fn_endRadioTransmission.sqf @@ -13,10 +13,10 @@ // ACRE if (isClass (configFile >> "CfgPatches" >> "acre_main")) then { - [-1] call acre_sys_core_fnc_handleMultiPttKeyPressUp; - [0] call acre_sys_core_fnc_handleMultiPttKeyPressUp; - [1] call acre_sys_core_fnc_handleMultiPttKeyPressUp; - [2] call acre_sys_core_fnc_handleMultiPttKeyPressUp; + [-1] call acre_core_fnc_handleMultiPttKeyPressUp; + [0] call acre_core_fnc_handleMultiPttKeyPressUp; + [1] call acre_core_fnc_handleMultiPttKeyPressUp; + [2] call acre_core_fnc_handleMultiPttKeyPressUp; }; // TFAR diff --git a/addons/frag/$PBOPREFIX$ b/addons/frag/$PBOPREFIX$ new file mode 100644 index 0000000000..ddf45c738b --- /dev/null +++ b/addons/frag/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\frag \ No newline at end of file diff --git a/addons/frag/CfgAmmo.hpp b/addons/frag/CfgAmmo.hpp new file mode 100644 index 0000000000..c9d13d3ce3 --- /dev/null +++ b/addons/frag/CfgAmmo.hpp @@ -0,0 +1,352 @@ +#define BASE_DRAG -0.01 +#define HD_MULT 5 +#define BASE_DRAG_HD (BASE_DRAG*HD_MULT) + +class CfgAmmo { + //class ace_arty_105mm_m1_m782_time; + //class ace_arty_105mm_m1_m782_prox: ace_arty_105mm_m1_m782_time {}; + //class ace_arty_105mm_m1_m782_delay: ace_arty_105mm_m1_m782_prox { + // ACE_FRAG_SKIP = 1; + //}; + class Bo_GBU12_LGB; + class Nou_GBU12 : Bo_GBU12_LGB { + ACE_FRAG_CLASSES[] = {"ACE_frag_large", "ACE_frag_large", "ACE_frag_large_HD", "ACE_frag_large", "ACE_frag_huge", "ACE_frag_huge_HD", "ACE_frag_huge"}; + ACE_FRAG_METAL = 140000; + ACE_FRAG_CHARGE = 87000; + ACE_FRAG_GURNEY_C = 2320; + ACE_FRAG_GURNEY_K = 1/2; + sideAirFriction = 0.04; + airFriction = 0.04; + laserLock = 0; + }; + + class GrenadeBase; + class Grenade; + class GrenadeHand: Grenade { + ACE_FRAG_SKIP = 0; + ACE_FRAG_FORCE = 1; + // This is a good high-drag frag type for grenades. + ACE_FRAG_CLASSES[] = {"ACE_frag_medium_HD"}; + /* + These values are based on the M67 Grenade, should be tweaked for + individual grenades. + */ + ACE_FRAG_METAL = 210; // metal in grams + ACE_FRAG_CHARGE = 185; // explosive in grams + ACE_FRAG_GURNEY_C = 2843; // Gurney velocity constant for explosive type. See: http://en.wikipedia.org/wiki/Gurney_equations + ACE_FRAG_GURNEY_K = 3/5; // Gurney shape factor, in this case a sphere. See: http://en.wikipedia.org/wiki/Gurney_equations + }; + class GrenadeHand_stone: GrenadeHand { + ACE_FRAG_SKIP = 1; + }; + class SmokeShell: GrenadeHand { + ACE_FRAG_SKIP = 1; + }; + + class RocketBase; + //class R_Hydra_HE: RocketBase { + // ACE_FRAG_SKIP = 1; + //}; + + //class R_57mm_HE: RocketBase { + // ACE_FRAG_SKIP = 1; + //}; + + class R_80mm_HE: RocketBase { + ACE_FRAG_SKIP = 1; + }; + + //class R_S8T_AT: RocketBase { + // ACE_FRAG_SKIP = 1; + //}; + + class BombCore; + class Bo_Mk82: BombCore { + ACE_FRAG_CLASSES[] = {"ACE_frag_large", "ACE_frag_large", "ACE_frag_large_HD", "ACE_frag_large", "ACE_frag_huge", "ACE_frag_huge_HD", "ACE_frag_huge"}; + ACE_FRAG_METAL = 140000; + ACE_FRAG_CHARGE = 87000; + ACE_FRAG_GURNEY_C = 2320; + ACE_FRAG_GURNEY_K = 1/2; + }; + + + class G_40mm_HE: GrenadeBase { + ACE_FRAG_SKIP = 0; + ACE_FRAG_FORCE = 1; + }; + + class ACE_G_40mm_HEDP: G_40mm_HE { + }; + class ACE_G_40mm_HE: ACE_G_40mm_HEDP { + }; + class ACE_G_40mm_Practice: ACE_G_40mm_HE { + ACE_FRAG_SKIP = 1; + }; + class ACE_G40mm_HE_VOG25P: G_40mm_HE { + ACE_FRAG_SKIP = 0; + ACE_FRAG_FORCE = 1; + }; + + //class R_SMAW_HEDP; + //class R_MEEWS_HEDP : R_SMAW_HEDP { + // ACE_FRAG_FORCE = 1; + // ACE_FRAG_MULTIPLIER = 1.2; + //}; + + //class MissileBase; + //class M_Hellfire_AT: MissileBase { + // ACE_FRAG_FORCE = 1; + // ACE_FRAG_MULTIPLIER = 1.75; + //}; + + /* + class B_762x51_Ball; + class ACE_frag_base: B_762x51_Ball { ////TODO: B_762x45_Ball no longer exists, is this a valid replacement? + model = "\A3\Weapons_f\ammo\shell"; + timeToLive = 12; + typicalSpeed = 800; + // Fix sounds + effectFly = "AmmoClassic"; + soundDefault1[] = {"A3\sounds_f\weapons\hits\concrete_1.wav",0.158114,1,30}; + soundDefault2[] = {"A3\sounds_f\weapons\hits\concrete_2.wav",0.158114,1,30}; + soundDefault3[] = {"A3\sounds_f\weapons\hits\concrete_3.wav",0.158114,1,30}; + soundDefault4[] = {"A3\sounds_f\weapons\hits\concrete_4.wav",0.158114,1,30}; + soundDefault5[] = {"A3\sounds_f\weapons\hits\concrete_5.wav",0.158114,1,30}; + soundDefault6[] = {"A3\sounds_f\weapons\hits\concrete_6.wav",0.158114,1,30}; + soundDefault7[] = {"A3\sounds_f\weapons\hits\concrete_7.wav",0.158114,1,30}; + soundDefault8[] = {"A3\sounds_f\weapons\hits\concrete_8.wav",0.158114,1,30}; + soundGroundSoft1[] = {"A3\sounds_f\weapons\hits\soft_ground_1.wav",0.02811705,1,30}; + soundGroundSoft2[] = {"A3\sounds_f\weapons\hits\soft_ground_2.wav",0.02811705,1,30}; + soundGroundSoft3[] = {"A3\sounds_f\weapons\hits\soft_ground_3.wav",0.02811705,1,30}; + soundGroundSoft4[] = {"A3\sounds_f\weapons\hits\soft_ground_4.wav",0.02811705,1,30}; + soundGroundSoft5[] = {"A3\sounds_f\weapons\hits\soft_ground_5.wav",0.02811705,1,30}; + soundGroundSoft6[] = {"A3\sounds_f\weapons\hits\soft_ground_6.wav",0.02811705,1,30}; + soundGroundSoft7[] = {"A3\sounds_f\weapons\hits\soft_ground_7.wav",0.02811705,1,30}; + soundGroundSoft8[] = {"A3\sounds_f\weapons\hits\soft_ground_8.wav",0.02811705,1,30}; + soundGroundHard1[] = {"A3\sounds_f\weapons\hits\hard_ground_1.wav",0.62946,1,40}; + soundGroundHard2[] = {"A3\sounds_f\weapons\hits\hard_ground_2.wav",0.62946,1,40}; + soundGroundHard3[] = {"A3\sounds_f\weapons\hits\hard_ground_3.wav",0.62946,1,40}; + soundGroundHard4[] = {"A3\sounds_f\weapons\hits\hard_ground_4.wav",0.62946,1,40}; + soundGroundHard5[] = {"A3\sounds_f\weapons\hits\hard_ground_5.wav",0.62946,1,40}; + soundGroundHard6[] = {"A3\sounds_f\weapons\hits\hard_ground_6.wav",0.62946,1,40}; + soundGroundHard7[] = {"A3\sounds_f\weapons\hits\hard_ground_7.wav",0.62946,1,40}; + soundGroundHard8[] = {"A3\sounds_f\weapons\hits\hard_ground_8.wav",0.62946,1,40}; + soundMetal1[] = {"A3\sounds_f\weapons\hits\metal_1.wav",0.158114,1,45}; + soundMetal2[] = {"A3\sounds_f\weapons\hits\metal_2.wav",0.158114,1,45}; + soundMetal3[] = {"A3\sounds_f\weapons\hits\metal_3.wav",0.158114,1,45}; + soundMetal4[] = {"A3\sounds_f\weapons\hits\metal_4.wav",0.158114,1,45}; + soundMetal5[] = {"A3\sounds_f\weapons\hits\metal_5.wav",0.158114,1,45}; + soundMetal6[] = {"A3\sounds_f\weapons\hits\metal_6.wav",0.158114,1,45}; + soundMetal7[] = {"A3\sounds_f\weapons\hits\metal_7.wav",0.158114,1,45}; + soundMetal8[] = {"A3\sounds_f\weapons\hits\metal_8.wav",0.158114,1,45}; + soundGlass1[] = {"A3\sounds_f\weapons\hits\glass_1.wav",0.177828,1,25}; + soundGlass2[] = {"A3\sounds_f\weapons\hits\glass_2.wav",0.177828,1,25}; + soundGlass3[] = {"A3\sounds_f\weapons\hits\glass_3.wav",0.177828,1,25}; + soundGlass4[] = {"A3\sounds_f\weapons\hits\glass_4.wav",0.177828,1,25}; + soundGlass5[] = {"A3\sounds_f\weapons\hits\glass_5.wav",0.177828,1,25}; + soundGlass6[] = {"A3\sounds_f\weapons\hits\glass_6.wav",0.177828,1,25}; + soundGlass7[] = {"A3\sounds_f\weapons\hits\glass_7.wav",0.177828,1,25}; + soundGlass8[] = {"A3\sounds_f\weapons\hits\glass_8.wav",0.177828,1,25}; + soundGlassArmored1[] = {"A3\sounds_f\weapons\hits\glass_arm_1.wav",0.177828,1,30}; + soundGlassArmored2[] = {"A3\sounds_f\weapons\hits\glass_arm_2.wav",0.177828,1,30}; + soundGlassArmored3[] = {"A3\sounds_f\weapons\hits\glass_arm_3.wav",0.177828,1,30}; + soundGlassArmored4[] = {"A3\sounds_f\weapons\hits\glass_arm_4.wav",0.177828,1,30}; + soundGlassArmored5[] = {"A3\sounds_f\weapons\hits\glass_arm_5.wav",0.177828,1,30}; + soundGlassArmored6[] = {"A3\sounds_f\weapons\hits\glass_arm_6.wav",0.177828,1,30}; + soundGlassArmored7[] = {"A3\sounds_f\weapons\hits\glass_arm_7.wav",0.177828,1,30}; + soundGlassArmored8[] = {"A3\sounds_f\weapons\hits\glass_arm_8.wav",0.177828,1,30}; + soundVehiclePlate1[] = {"A3\sounds_f\weapons\hits\metal_plate_1.wav",0.281170,1,40}; + soundVehiclePlate2[] = {"A3\sounds_f\weapons\hits\metal_plate_2.wav",0.281170,1,40}; + soundVehiclePlate3[] = {"A3\sounds_f\weapons\hits\metal_plate_3.wav",0.281170,1,40}; + soundVehiclePlate4[] = {"A3\sounds_f\weapons\hits\metal_plate_4.wav",0.281170,1,40}; + soundVehiclePlate5[] = {"A3\sounds_f\weapons\hits\metal_plate_5.wav",0.281170,1,40}; + soundVehiclePlate6[] = {"A3\sounds_f\weapons\hits\metal_plate_6.wav",0.281170,1,40}; + soundVehiclePlate7[] = {"A3\sounds_f\weapons\hits\metal_plate_7.wav",0.281170,1,40}; + soundVehiclePlate8[] = {"A3\sounds_f\weapons\hits\metal_plate_8.wav",0.281170,1,40}; + soundWood1[] = {"A3\sounds_f\weapons\hits\wood_1.wav",0.158114,1,30}; + soundWood2[] = {"A3\sounds_f\weapons\hits\wood_2.wav",0.158114,1,30}; + soundWood3[] = {"A3\sounds_f\weapons\hits\wood_3.wav",0.158114,1,30}; + soundWood4[] = {"A3\sounds_f\weapons\hits\wood_4.wav",0.158114,1,30}; + soundWood5[] = {"A3\sounds_f\weapons\hits\wood_5.wav",0.158114,1,30}; + soundWood6[] = {"A3\sounds_f\weapons\hits\wood_6.wav",0.158114,1,30}; + soundWood7[] = {"A3\sounds_f\weapons\hits\wood_7.wav",0.158114,1,30}; + soundWood8[] = {"A3\sounds_f\weapons\hits\wood_8.wav",0.158114,1,30}; + soundHitBody1[] = {"A3\sounds_f\weapons\hits\body_1.wav",0.0177828,1,25}; + soundHitBody2[] = {"A3\sounds_f\weapons\hits\body_2.wav",0.0177828,1,25}; + soundHitBody3[] = {"A3\sounds_f\weapons\hits\body_3.wav",0.0177828,1,25}; + soundHitBody4[] = {"A3\sounds_f\weapons\hits\body_4.wav",0.0177828,1,25}; + soundHitBody5[] = {"A3\sounds_f\weapons\hits\body_5.wav",0.0177828,1,25}; + soundHitBody6[] = {"A3\sounds_f\weapons\hits\body_6.wav",0.0177828,1,25}; + soundHitBody7[] = {"A3\sounds_f\weapons\hits\body_7.wav",0.0177828,1,25}; + soundHitBody8[] = {"A3\sounds_f\weapons\hits\body_8.wav",0.0177828,1,25}; + soundHitBuilding1[] = {"A3\sounds_f\weapons\hits\building_1.wav",0.251189,1,30}; + soundHitBuilding2[] = {"A3\sounds_f\weapons\hits\building_2.wav",0.251189,1,30}; + soundHitBuilding3[] = {"A3\sounds_f\weapons\hits\building_3.wav",0.251189,1,30}; + soundHitBuilding4[] = {"A3\sounds_f\weapons\hits\building_4.wav",0.251189,1,30}; + soundHitBuilding5[] = {"A3\sounds_f\weapons\hits\building_5.wav",0.251189,1,30}; + soundHitBuilding6[] = {"A3\sounds_f\weapons\hits\building_6.wav",0.251189,1,30}; + soundHitBuilding7[] = {"A3\sounds_f\weapons\hits\building_7.wav",0.251189,1,30}; + soundHitBuilding8[] = {"A3\sounds_f\weapons\hits\building_8.wav",0.251189,1,30}; + soundHitFoliage1[] = {"A3\sounds_f\weapons\hits\foliage_1.wav",0.177828,1,25}; + soundHitFoliage2[] = {"A3\sounds_f\weapons\hits\foliage_2.wav",0.177828,1,25}; + soundHitFoliage3[] = {"A3\sounds_f\weapons\hits\foliage_3.wav",0.177828,1,25}; + soundHitFoliage4[] = {"A3\sounds_f\weapons\hits\foliage_4.wav",0.177828,1,25}; + soundHitFoliage5[] = {"A3\sounds_f\weapons\hits\foliage_5.wav",0.177828,1,25}; + soundHitFoliage6[] = {"A3\sounds_f\weapons\hits\foliage_6.wav",0.177828,1,25}; + soundHitFoliage7[] = {"A3\sounds_f\weapons\hits\foliage_7.wav",0.177828,1,25}; + soundHitFoliage8[] = {"A3\sounds_f\weapons\hits\foliage_8.wav",0.177828,1,25}; + soundPlastic1[] = {"A3\sounds_f\weapons\hits\plastic_1.wav",0.177828,1,25}; + soundPlastic2[] = {"A3\sounds_f\weapons\hits\plastic_2.wav",0.177828,1,25}; + soundPlastic3[] = {"A3\sounds_f\weapons\hits\plastic_3.wav",0.177828,1,25}; + soundPlastic4[] = {"A3\sounds_f\weapons\hits\plastic_4.wav",0.177828,1,25}; + soundPlastic5[] = {"A3\sounds_f\weapons\hits\plastic_5.wav",0.177828,1,25}; + soundPlastic6[] = {"A3\sounds_f\weapons\hits\plastic_6.wav",0.177828,1,25}; + soundPlastic7[] = {"A3\sounds_f\weapons\hits\plastic_7.wav",0.177828,1,25}; + soundPlastic8[] = {"A3\sounds_f\weapons\hits\plastic_8.wav",0.177828,1,25}; + soundConcrete1[] = {"A3\sounds_f\weapons\hits\concrete_1.wav",0.177828,1,35}; + soundConcrete2[] = {"A3\sounds_f\weapons\hits\concrete_2.wav",0.177828,1,35}; + soundConcrete3[] = {"A3\sounds_f\weapons\hits\concrete_3.wav",0.177828,1,35}; + soundConcrete4[] = {"A3\sounds_f\weapons\hits\concrete_4.wav",0.177828,1,35}; + soundConcrete5[] = {"A3\sounds_f\weapons\hits\concrete_5.wav",0.177828,1,35}; + soundConcrete6[] = {"A3\sounds_f\weapons\hits\concrete_6.wav",0.177828,1,35}; + soundConcrete7[] = {"A3\sounds_f\weapons\hits\concrete_7.wav",0.177828,1,35}; + soundConcrete8[] = {"A3\sounds_f\weapons\hits\concrete_8.wav",0.177828,1,35}; + soundRubber1[] = {"A3\sounds_f\weapons\hits\tyre_1.wav",0.158114,1,25}; + soundRubber2[] = {"A3\sounds_f\weapons\hits\tyre_2.wav",0.158114,1,25}; + soundRubber3[] = {"A3\sounds_f\weapons\hits\tyre_3.wav",0.158114,1,25}; + soundRubber4[] = {"A3\sounds_f\weapons\hits\tyre_4.wav",0.158114,1,25}; + soundRubber5[] = {"A3\sounds_f\weapons\hits\tyre_5.wav",0.158114,1,25}; + soundRubber6[] = {"A3\sounds_f\weapons\hits\tyre_6.wav",0.158114,1,25}; + soundRubber7[] = {"A3\sounds_f\weapons\hits\tyre_7.wav",0.158114,1,25}; + soundRubber8[] = {"A3\sounds_f\weapons\hits\tyre_8.wav",0.158114,1,25}; + soundWater1[] = {"A3\sounds_f\weapons\hits\water_01.wav",0.158114,1,25}; + soundWater2[] = {"A3\sounds_f\weapons\hits\water_02.wav",0.158114,1,25}; + soundWater3[] = {"A3\sounds_f\weapons\hits\water_03.wav",0.158114,1,25}; + soundWater4[] = {"A3\sounds_f\weapons\hits\water_04.wav",0.158114,1,25}; + soundWater5[] = {"A3\sounds_f\weapons\hits\water_05.wav",0.158114,1,25}; + soundWater6[] = {"A3\sounds_f\weapons\hits\water_06.wav",0.158114,1,25}; + soundWater7[] = {"A3\sounds_f\weapons\hits\water_07.wav",0.158114,1,25}; + soundWater8[] = {"A3\sounds_f\weapons\hits\water_08.wav",0.158114,1,25}; + hitGroundSoft[] = {"soundGroundSoft1",0.2,"soundGroundSoft2",0.2,"soundGroundSoft3",0.1,"soundGroundSoft4",0.1,"soundGroundSoft5",0.1,"soundGroundSoft6",0.1,"soundGroundSoft7",0.1,"soundGroundSoft8",0.1}; + hitGroundHard[] = {"soundGroundHard1",0.2,"soundGroundHard2",0.2,"soundGroundHard3",0.1,"soundGroundHard4",0.1,"soundGroundHard5",0.1,"soundGroundHard6",0.1,"soundGroundHard7",0.1,"soundGroundHard8",0.1}; + hitMan[] = {"soundHitBody1",0.125,"soundHitBody2",0.125,"soundHitBody3",0.125,"soundHitBody4",0.125,"soundHitBody5",0.125,"soundHitBody6",0.125,"soundHitBody7",0.125,"soundHitBody8",0.125}; + hitArmor[] = {"soundVehiclePlate1",0.125,"soundVehiclePlate2",0.125,"soundVehiclePlate3",0.125,"soundVehiclePlate4",0.125,"soundVehiclePlate5",0.125,"soundVehiclePlate6",0.125,"soundVehiclePlate7",0.125,"soundVehiclePlate8",0.125}; + hitBuilding[] = {"soundHitBuilding1",0.2,"soundHitBuilding2",0.2,"soundHitBuilding3",0.1,"soundHitBuilding4",0.1,"soundHitBuilding5",0.1,"soundHitBuilding6",0.1,"soundHitBuilding7",0.1,"soundHitBuilding8",0.1}; + hitFoliage[] = {"soundHitFoliage1",0.125,"soundHitFoliage2",0.125,"soundHitFoliage3",0.125,"soundHitFoliage4",0.125,"soundHitFoliage5",0.125,"soundHitFoliage6",0.125,"soundHitFoliage7",0.125,"soundHitFoliage8",0.125}; + hitWood[] = {"soundWood1",0.125,"soundWood2",0.125,"soundWood3",0.125,"soundWood4",0.125,"soundWood5",0.125,"soundWood6",0.125,"soundWood7",0.125,"soundWood8",0.125}; + hitGlass[] = {"soundGlass1",0.125,"soundGlass2",0.125,"soundGlass3",0.125,"soundGlass4",0.125,"soundGlass5",0.125,"soundGlass6",0.125,"soundGlass7",0.125,"soundGlass8",0.125}; + hitGlassArmored[] = {"soundGlassArmored1",0.125,"soundGlassArmored2",0.125,"soundGlassArmored3",0.125,"soundGlassArmored4",0.125,"soundGlassArmored5",0.125,"soundGlassArmored6",0.125,"soundGlassArmored7",0.125,"soundGlassArmored8",0.125}; + hitConcrete[] = {"soundConcrete1",0.125,"soundConcrete2",0.125,"soundConcrete3",0.125,"soundConcrete4",0.125,"soundConcrete5",0.125,"soundConcrete6",0.125,"soundConcrete7",0.125,"soundConcrete8",0.125}; + hitRubber[] = {"soundRubber1",0.125,"soundRubber2",0.125,"soundRubber3",0.125,"soundRubber4",0.125,"soundRubber5",0.125,"soundRubber6",0.125,"soundRubber7",0.125,"soundRubber8",0.125}; + hitPlastic[] = {"soundPlastic1",0.125,"soundPlastic2",0.125,"soundPlastic3",0.125,"soundPlastic4",0.125,"soundPlastic5",0.125,"soundPlastic6",0.125,"soundPlastic7",0.125,"soundPlastic8",0.125}; + hitDefault[] = {"soundDefault1",0.2,"soundDefault2",0.2,"soundDefault3",0.1,"soundDefault4",0.1,"soundDefault5",0.1,"soundDefault6",0.1,"soundDefault7",0.1,"soundDefault8",0.1}; + hitMetal[] = {"soundMetal1",0.125,"soundMetal2",0.125,"soundMetal3",0.125,"soundMetal4",0.125,"soundMetal5",0.125,"soundMetal6",0.125,"soundMetal7",0.125,"soundMetal8",0.125}; + hitMetalplate[] = {"soundVehiclePlate1",0.125,"soundVehiclePlate2",0.125,"soundVehiclePlate3",0.125,"soundVehiclePlate4",0.125,"soundVehiclePlate5",0.125,"soundVehiclePlate6",0.125,"soundVehiclePlate7",0.125,"soundVehiclePlate8",0.125}; + hitWater[] = {"soundWater1",0.125,"soundWater2",0.125,"soundWater3",0.125,"soundWater4",0.125,"soundWater5",0.125,"soundWater6",0.125,"soundWater7",0.125,"soundWater8",0.125}; + bulletFly1[] = {"A3\sounds_f\weapons\hits\bullet_by_1.wav",1,1,35}; + bulletFly2[] = {"A3\sounds_f\weapons\hits\bullet_by_2.wav",1,1,35}; + bulletFly3[] = {"A3\sounds_f\weapons\hits\bullet_by_3.wav",1,1,35}; + bulletFly4[] = {"A3\sounds_f\weapons\hits\bullet_by_4.wav",1,1,35}; + bulletFly5[] = {"A3\sounds_f\weapons\hits\bullet_by_5.wav",1,1,35}; + bulletFly6[] = {"A3\sounds_f\weapons\hits\bullet_by_6.wav",1,1,35}; + bulletFly7[] = {"A3\sounds_f\weapons\hits\bullet_by_7.wav",1,1,35}; + bulletFly8[] = {"A3\sounds_f\weapons\hits\bullet_by_8.wav",1,1,35}; + bulletFly[] = {"bulletFly1",0.166,"bulletFly2",0.166,"bulletFly3",0.166,"bulletFly4",0.166,"bulletFly5",0.166,"bulletFly6",0.167,"bulletFly7",0.166,"bulletFly8",0.167}; + supersonicCrackNear[] = {"A3\sounds_f\weapons\hits\sscrack1.wav",1,1,35}; + supersonicCrackFar[] = {"A3\sounds_f\weapons\hits\sscrack2.wav",1,1,135}; + }; + */ + + class B_65x39_Caseless; + class ACE_frag_base: B_65x39_Caseless { + timeToLive = 12; + typicalSpeed = 1500; + deflecting = 65; + }; + + class ACE_frag_tiny: ACE_frag_base { + hit = 6; + airFriction = BASE_DRAG; + caliber = 0.75; + }; + + class ACE_frag_tiny_HD: ACE_frag_base { + hit = 6; + airFriction = BASE_DRAG_HD; + caliber = 0.75; + }; + + class ACE_frag_small: ACE_frag_base { + hit = 12; + airFriction = BASE_DRAG*0.9; + }; + + class ACE_frag_small_HD: ACE_frag_base { + hit = 12; + airFriction = BASE_DRAG_HD*0.9; + }; + + class ACE_frag_medium: ACE_frag_base { + hit = 14; + airFriction = BASE_DRAG*0.75; + caliber = 1.2; + }; + + class ACE_frag_medium_HD: ACE_frag_base { + hit = 14; + airFriction = BASE_DRAG_HD*0.75; + caliber = 1.2; + }; + + class ACE_frag_large: ACE_frag_base { + hit = 28; + indirectHit = 2; + indirectHitRange = 0.25; + airFriction = BASE_DRAG*0.65; + caliber = 2; + explosive = 0; + + }; + + class ACE_frag_large_HD: ACE_frag_large { + hit = 28; + indirectHit = 2; + indirectHitRange = 0.25; + airFriction = BASE_DRAG_HD*0.65; + caliber = 2; + + + }; + + class ACE_frag_huge: ACE_frag_large { + hit = 40; + indirectHit = 4; + indirectHitRange = 0.5; + airFriction = BASE_DRAG*0.5; + caliber = 2.8; + }; + + class ACE_frag_huge_HD: ACE_frag_large { + hit = 40; + indirectHit = 4; + indirectHitRange = 0.5; + airFriction = BASE_DRAG_HD*0.5; + caliber = 2.8; + }; + + class ACE_frag_spall_small: ACE_frag_small { + timeToLive = 0.1; + }; + + class ACE_frag_spall_medium: ACE_frag_medium { + timeToLive = 0.15; + }; + + class ACE_frag_spall_large: ACE_frag_large { + timeToLive = 0.25; + }; + + class ACE_frag_spall_huge: ACE_frag_huge { + timeToLive = 0.3; + }; +}; diff --git a/addons/frag/CfgEventhandlers.hpp b/addons/frag/CfgEventhandlers.hpp new file mode 100644 index 0000000000..121b24d062 --- /dev/null +++ b/addons/frag/CfgEventhandlers.hpp @@ -0,0 +1,17 @@ +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_pre_init)); + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_post_init)); + }; +}; + +class Extended_FiredBIS_EventHandlers { + class AllVehicles { + ADDON = QUOTE(_this call FUNC(fired)); + }; +}; diff --git a/addons/frag/CfgVehicles.hpp b/addons/frag/CfgVehicles.hpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/addons/frag/XEH_post_init.sqf b/addons/frag/XEH_post_init.sqf new file mode 100644 index 0000000000..25cb5132c8 --- /dev/null +++ b/addons/frag/XEH_post_init.sqf @@ -0,0 +1,17 @@ +#include "script_component.hpp" +[QUOTE(ffsBIS), "oneachframe", QUOTE(FUNC(onFrame))] call BIS_fnc_addStackedEventHandler; +if(isServer) then { + [QGVAR(frag_eh), { _this call FUNC(frago); }] call CBA_fnc_addClientToServerEventhandler; +}; +GVAR(replacedBisArtyWrapper) = false; +[] spawn { + waitUntil { + if(!(isNil "BIS_ARTY_F_ShellFlight")) then { + ACE_WRAPPER_BIS_ARTY_F_ShellFlight = BIS_ARTY_F_ShellFlight; + BIS_ARTY_F_ShellFlight = FUNC(BIS_ARTY_WRAPPER); + GVAR(replacedBisArtyWrapper) = true; + }; + sleep 4; + GVAR(replacedBisArtyWrapper) + }; +}; diff --git a/addons/frag/XEH_pre_Init.sqf b/addons/frag/XEH_pre_Init.sqf new file mode 100644 index 0000000000..406e6e7f63 --- /dev/null +++ b/addons/frag/XEH_pre_Init.sqf @@ -0,0 +1,45 @@ +#include "script_component.hpp" + +#define ACE_TRACE_DRAW_INC 1 +ADDON = false; + +PREP(fired); +PREP(frago); +PREP(trackFragRound); +PREP(spallTrack); +PREP(doSpall); +PREP(vectorDiffFast); + +GVAR(trackedObjects) = []; +GVAR(blackList) = []; +GVAR(traceFrags) = false; + +GVAR(replacedBisArtyWrapper) = false; + +GVAR(TOTALFRAGS) = 0; + +GVAR(spallIsTrackingCount) = 0; +GVAR(spallHPData) = []; + +GVAR(traces) = []; +GVAR(tracesStarted) = false; +GVAR(traceID) = -1; +GVAR(autoTrace) = true; + + +// * Other Shit */ +PREP(frag_trace); +PREP(denyFrag); +PREP(BIS_ARTY_WRAPPER); +PREP(startTracing); +PREP(stopTracing); +PREP(clearTraces); +PREP(trackTrace); +PREP(addTrack); +PREP(drawTraces); +PREP(removeTrack); +PREP(spallHP); +PREP(addBlackList); +PREP(addManualTrack); + +ADDON = true; diff --git a/addons/frag/config.cpp b/addons/frag/config.cpp new file mode 100644 index 0000000000..acde4575b2 --- /dev/null +++ b/addons/frag/config.cpp @@ -0,0 +1,16 @@ +#include "script_component.hpp" +class CfgPatches { + class ADDON { + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { "A3_Misc_F", "A3_Weapons_F" }; + version = VERSION; + author[] = {"Nou"}; + }; +}; + +//PRELOAD_ADDONS; + +#include "CfgEventhandlers.hpp" +#include "CfgAmmo.hpp" diff --git a/addons/frag/data/icon/ace_frag_ico_ca.paa b/addons/frag/data/icon/ace_frag_ico_ca.paa new file mode 100644 index 0000000000..54114e391c Binary files /dev/null and b/addons/frag/data/icon/ace_frag_ico_ca.paa differ diff --git a/addons/frag/fnc_BIS_ARTY_WRAPPER.sqf b/addons/frag/fnc_BIS_ARTY_WRAPPER.sqf new file mode 100644 index 0000000000..ee7881277b --- /dev/null +++ b/addons/frag/fnc_BIS_ARTY_WRAPPER.sqf @@ -0,0 +1,13 @@ +#include "script_component.hpp" +_ret = [(_this select 6)] call FUNC(removeTrack); +if(!_ret) then { + [(_this select 6)] call FUNC(addBlackList); +}; +_this call ACE_WRAPPER_BIS_ARTY_F_ShellFlight; +_catEntry = BIS_ARTY_SHELLCAT select ((count BIS_ARTY_SHELLCAT) - 1); +_shell = _catEntry select 0; +_ARTY_DeployOnImpact = getText (configFile >> "CfgAmmo" >> "ARTY_DeployOnImpact"); +if(_ARTY_DeployOnImpact == "") then { + _this set[6, _shell]; + _this call FUNC(fired); +}; \ No newline at end of file diff --git a/addons/frag/fnc_addBlackList.sqf b/addons/frag/fnc_addBlackList.sqf new file mode 100644 index 0000000000..f7b3faf902 --- /dev/null +++ b/addons/frag/fnc_addBlackList.sqf @@ -0,0 +1,4 @@ +#include "script_component.hpp" +private ["_round"]; +_round = _this select 0; +GVAR(blackList) set[(count GVAR(blackList)), _round]; \ No newline at end of file diff --git a/addons/frag/fnc_addManualTrack.sqf b/addons/frag/fnc_addManualTrack.sqf new file mode 100644 index 0000000000..1719842240 --- /dev/null +++ b/addons/frag/fnc_addManualTrack.sqf @@ -0,0 +1,7 @@ +#include "script_component.hpp" +private ["_round"]; +_round = _this select 0; +if(alive _round) then { + GVAR(trackedObjects) set[(count GVAR(trackedObjects)), _round]; + [FUNC(trackFragRound), 0, [_round, (getPosASL _round), (velocity _round), (typeOf _round), time, objNull, false, 0, 0]] call cba_fnc_addPerFrameHandler; +}; \ No newline at end of file diff --git a/addons/frag/fnc_addTrack.sqf b/addons/frag/fnc_addTrack.sqf new file mode 100644 index 0000000000..4ffaef5a7c --- /dev/null +++ b/addons/frag/fnc_addTrack.sqf @@ -0,0 +1,20 @@ +#include "script_component.hpp" +if(GVAR(autoTrace)) then { + [] call FUNC(startTracing); +}; + +// setAccTime 0.05; +_index = (count GVAR(traces)); +_obj = _this select 1; +_origin = _this select 0; +_color = [1,0,0,1]; +if((count _this) > 2) then { + _color = _this select 2; +}; +_positions = []; +_objVel = velocity _obj; +_objTVel = sqrt((_objVel select 0)^2 + (_objVel select 1)^2 + (_objVel select 2)^2); +_positions set[(count _positions), [(getPos _obj), _objTVel]]; +_data = [_origin, typeOf _origin, typeOf _obj, _objTVel, _positions, _color]; +GVAR(traces) set[_index, _data]; +[FUNC(trackTrace), 0, [_obj, _index, time]] call cba_fnc_addPerFrameHandler; \ No newline at end of file diff --git a/addons/frag/fnc_clearTraces.sqf b/addons/frag/fnc_clearTraces.sqf new file mode 100644 index 0000000000..b301094044 --- /dev/null +++ b/addons/frag/fnc_clearTraces.sqf @@ -0,0 +1,2 @@ +#include "script_component.hpp" +GVAR(traces) = []; \ No newline at end of file diff --git a/addons/frag/fnc_denyFrag.sqf b/addons/frag/fnc_denyFrag.sqf new file mode 100644 index 0000000000..5459f0160a --- /dev/null +++ b/addons/frag/fnc_denyFrag.sqf @@ -0,0 +1,7 @@ +#include "script_component.hpp" + +private ["_ret"]; +_ret = [(_this select 0)] call FUNC(removeTrack); +if(!_ret) then { + [(_this select 0)] call FUNC(addBlackList); +}; \ No newline at end of file diff --git a/addons/frag/fnc_doSpall.sqf b/addons/frag/fnc_doSpall.sqf new file mode 100644 index 0000000000..92b67e0256 --- /dev/null +++ b/addons/frag/fnc_doSpall.sqf @@ -0,0 +1,169 @@ +//fnc_doSpall.sqf +#include "script_component.hpp" +#ifdef DEBUG_MODE_FULL + GVAR(traceFrags) = true; +#endif +// player sideChat "WAAAAAAAAAAAAAAAAAAAAA"; +private ["_params", "_initialData", "_hpData", "_roundType", "_round", "_object", "_caliber", "_explosive", + "_idh", "_alive", "_exit", "_vm", "_velocity", "_unitDir", "_oldVelocity", "_curVelocity", "_diff", "_polar", + "_pos", "_spallPos", "_i", "_pos1", "_pos2", "_blah", "_data", "_spallPolar", "_c", "_warn", "_m", "_k", + "_gC", "_shellType", "_fragPower", "_spread", "_spallCount", "_elev", "_dir", "_vel", "_spallFragVect", + "_fragment"]; + + +_params = _this select 0; +[(_this select 1)] call cba_fnc_removePerFrameHandler; +_hitData = _params select 0; +_initialData = GVAR(spallHPData) select (_hitData select 0); +_hpData = (_hitData select 1) select (_params select 1); + + +_object = _hpData select 0; +_object removeEventHandler ["hitPart", _initialData select 0]; +_foundObjects = _initialData select 7; +_index = _foundObjects find _object; +if(_index != -1) then { + _foundObjecsts set[_index, nil]; +}; + +_roundType = (_initialData select 2); +_round = (_initialData select 3); +_object = (_initialData select 1); + +_caliber = getNumber(configFile >> "CfgAmmo" >> _roundType >> "caliber"); +_explosive = getNumber(configFile >> "CfgAmmo" >> _roundType >> "explosive"); +_idh = getNumber(configFile >> "CfgAmmo" >> _roundType >> "indirectHitRange"); + +_alive = true; +if(!alive _round && (_initialData select 6) == 1) then { + _alive = false; +}; + +if(_alive || {_caliber >= 2.5} || {(_explosive > 0 && {_idh >= 1})}) then { + // player sideChat format["BBBB"]; + _exit = false; + _vm = 1; + _velocity = _initialData select 5; + _unitDir = _velocity call BIS_fnc_unitVector; + + _oldVelocity = _velocity call BIS_fnc_magnitude; + _curVelocity = (velocity _round) call BIS_fnc_magnitude; + + if(alive _round) then { + _diff = [_velocity, (velocity _round)] call FUNC(vectorDiffFast); + _polar = _diff call CBA_fnc_vect2polar; + // player sideChat format["polar: %1", _polar]; + if((abs(_polar select 1) > 45 || abs(_polar select 2) > 45)) then { + if(_caliber < 2.5) then { + // player sideChat format["exit!"]; + _exit = true; + } else { + _vm = 1-(_curVelocity/_oldVelocity); + }; + }; + }; + if(!_exit) then { + _unitDir = _velocity call BIS_fnc_unitVector; + _pos = _hpData select 3; + _spallPos = nil; + for "_i" from 0 to 100 do { + _pos1 = [ + (_pos select 0) + (((_unitDir select 0)*0.01)*_i), + (_pos select 1) + (((_unitDir select 1)*0.01)*_i), + (_pos select 2) + (((_unitDir select 2)*0.01)*_i) + ]; + _pos2 = [ + (_pos select 0) + (((_unitDir select 0)*0.01)*(_i+1)), + (_pos select 1) + (((_unitDir select 1)*0.01)*(_i+1)), + (_pos select 2) + (((_unitDir select 2)*0.01)*(_i+1)) + ]; + // _blah = [_object, "FIRE"] intersect [_object worldToModel (ASLtoATL _pos1), _object worldToModel (ASLtoATL _pos2)]; + // diag_log text format["b: %1", _blah]; + + // _data = [nil, nil, nil, 1, [[ASLtoATL _pos1, 1], [ASLtoATL _pos2, 1]]]; + // NOU_TRACES set[(count NOU_TRACES), _data]; + + if(!lineIntersects [_pos1, _pos2]) exitWith { + // player sideChat format["FOUND!"]; + _spallPos = _pos2; + }; + }; + if(!isNil "_spallPos") then { + _spallPolar = _velocity call CBA_fnc_vect2polar; + + if(_explosive > 0) then { + // player sideChat format["EXPLOSIVE!"]; + _warn = false; + _c = getNumber(configFile >> "CfgAmmo" >> _roundType >> "ACE_frag_CHARGE"); + if(_c == 0) then { _c = 1; _warn = true;}; + _m = getNumber(configFile >> "CfgAmmo" >> _roundType >> "ACE_frag_METAL"); + if(_m == 0) then { _m = 2; _warn = true;}; + _k = getNumber(configFile >> "CfgAmmo" >> _roundType >> "ACE_frag_GURNEY_K"); + if(_k == 0) then { _k = 1/2; _warn = true;}; + _gC = getNumber(configFile >> "CfgAmmo" >> _roundType >> "ACE_frag_GURNEY_C"); + if(_gC == 0) then { _gC = 2440; _warn = true;}; + + if(_warn) then { + diag_log text format["Ammo class %1 lacks proper explosive properties definitions for frag!", _roundType]; //TODO: turn this off when we get closer to release + }; + + _fragPower = (((_m/_c)+_k)^-(1/2))*_gC; + _spallPolar set[0, _fragPower*0.66]; + }; + + _fragTypes = [ + "ACE_frag_spall_small", "ACE_frag_spall_small", "ACE_frag_spall_small", + "ACE_frag_spall_small","ACE_frag_spall_medium","ACE_frag_spall_medium","ACE_frag_spall_medium", + "ACE_frag_spall_medium", "ACE_frag_spall_large", "ACE_frag_spall_large", "ACE_frag_spall_huge", + "ACE_frag_spall_huge" + + ]; + + // diag_log text format["SPALL POWER: %1", _spallPolar select 0]; + _spread = 15+(random 25); + _spallCount = 5+(random 10); + for "_i" from 1 to _spallCount do { + _elev = ((_spallPolar select 2)-_spread)+(random (_spread*2)); + _dir = ((_spallPolar select 1)-_spread)+(random (_spread*2)); + if(abs _elev > 90) then { + _dir = _dir + 180; + }; + _dir = _dir % 360; + _vel = (_spallPolar select 0)*0.33*_vm; + _vel = (_vel-(_vel*0.25))+(random (_vel*0.5)); + + _spallFragVect = [_vel, _dir, _elev] call CBA_fnc_polar2vect; + _fragType = round (random ((count _fragTypes)-1)); + _fragment = (_fragTypes select _fragType) createVehicleLocal [0,0,10000]; + _fragment setPosASL _spallPos; + _fragment setVelocity _spallFragVect; + // [fnc_spallTrackPFH, 0, [_fragment, diag_tickTime]] call cba_fnc_addPerFrameHandler; + if(GVAR(traceFrags)) then { + [player, _fragment, [1,0.5,0,1]] call FUNC(addTrack); + }; + }; + _spread = 5+(random 5); + _spallCount = 3+(random 5); + for "_i" from 1 to _spallCount do { + _elev = ((_spallPolar select 2)-_spread)+(random (_spread*2)); + _dir = ((_spallPolar select 1)-_spread)+(random (_spread*2)); + if(abs _elev > 90) then { + _dir = _dir + 180; + }; + _dir = _dir % 360; + _vel = (_spallPolar select 0)*0.55*_vm; + _vel = (_vel-(_vel*0.25))+(random (_vel*0.5)); + + _spallFragVect = [_vel, _dir, _elev] call CBA_fnc_polar2vect; + _fragType = round (random ((count _fragTypes)-1)); + _fragment = (_fragTypes select _fragType) createVehicleLocal [0,0,10000]; + _fragment setPosASL _spallPos; + _fragment setVelocity _spallFragVect; + // [fnc_spallTrackPFH, 0, [_fragment, diag_tickTime]] call cba_fnc_addPerFrameHandler; + if(GVAR(traceFrags)) then { + [player, _fragment, [1,0,0,1]] call FUNC(addTrack); + }; + }; + }; + }; +}; \ No newline at end of file diff --git a/addons/frag/fnc_drawTraces.sqf b/addons/frag/fnc_drawTraces.sqf new file mode 100644 index 0000000000..8e3ab6146e --- /dev/null +++ b/addons/frag/fnc_drawTraces.sqf @@ -0,0 +1,32 @@ +#include "script_component.hpp" +{ + _positions = _x select 4; + _color = _x select 5; + _index = 0; + _max = count _positions; + _startSpeed = (_positions select 0) select 1; + if(_startSpeed <= 0) then { + _startSpeed = 0.01; + }; + _lastSpd = []; + _lastPos = []; + while {_index < _max} do { + _data1 = _positions select _index; + _data2 = nil; + if(_index + ACE_TRACE_DRAW_INC >= _max) then { + _data2 = _positions select (_max - 1); + } else { + _data2 = _positions select (_index + ACE_TRACE_DRAW_INC); + }; + + _pos1 = _data1 select 0; + _pos2 = _data2 select 0; + _index = _index + ACE_TRACE_DRAW_INC; + + + drawLine3D [_pos1, _pos2, _color]; + _lastPos = _pos2; + _lastSpd = _data1 select 1; + }; + // drawIcon3D ["", [1,0,0,1], _lastPos, 0, 0, 0, format["%1m/s", _lastSpd], 1, 0.05, "PuristaMedium"]; +} forEach GVAR(traces); \ No newline at end of file diff --git a/addons/frag/fnc_fired.sqf b/addons/frag/fnc_fired.sqf new file mode 100644 index 0000000000..5910d2481b --- /dev/null +++ b/addons/frag/fnc_fired.sqf @@ -0,0 +1,50 @@ +#include "script_component.hpp" +/* +private ["_gun", "_type", "_round", "_doFragTrack", "_doSpall"]; +if !(isNil QGVAR(enabled) && {GVAR(enabled)}) exitWith {}; + +_gun = _this select 0; +_type = _this select 4; +_round = _this select 6; + +if(_round in GVAR(blackList)) exitWith { + GVAR(blackList) = GVAR(blackList) - [_round]; +}; + +_doFragTrack = false; +if(_gun == player) then { + _doFragTrack = true; +} else { + if((gunner _gun) == player) then { + _doFragTrack = true; + } else { + if(local _gun && {!(isPlayer (gunner _gun))} && {!(isPlayer _gun)}) then { + _doFragTrack = true; + }; + }; +}; +_doSpall = true; +if(_doSpall) then { + if(GVAR(spallIsTrackingCount) <= 0) then { + GVAR(spallHPData) = []; + }; + if(GVAR(spallIsTrackingCount) > 5) then { + // player sideChat "LIMT!"; + _doSpall = false; + } else { + GVAR(spallIsTrackingCount) = GVAR(spallIsTrackingCount) + 1; + }; +}; +// player sideChat format["c: %1", GVAR(spallIsTrackingCount)]; +[player, _round, [1,0,0,1]] call FUNC(addTrack); +if(_doFragTrack && alive _round) then { + GVAR(trackedObjects) set[(count GVAR(trackedObjects)), _round]; + _spallTrack = []; + _spallTrackID = []; + [FUNC(trackFragRound), 0, [_round, (getPosASL _round), (velocity _round), _type, time, _gun, _doSpall, _spallTrack, _spallTrackID]] call cba_fnc_addPerFrameHandler; + if(_doSpall) then { + [_round, 2, _spallTrack, _spallTrackID] call FUNC(spallTrack); + }; + // player sideChat "WTF2"; +}; +*/ \ No newline at end of file diff --git a/addons/frag/fnc_frag_trace.sqf b/addons/frag/fnc_frag_trace.sqf new file mode 100644 index 0000000000..9b0c8dc3db --- /dev/null +++ b/addons/frag/fnc_frag_trace.sqf @@ -0,0 +1,10 @@ +#include "script_component.hpp" + +private ["_params", "_shell"]; +_params = _this select 0; +_shell = _params select 0; +if(alive _shell) then { + drop ["\Ca\Data\Cl_basic","","Billboard",1,30,(getPos _shell),[0,0,0],1,1.275,1.0,0.0,[0.5],[[0,1,0,1]],[0],0.0,2.0,"","",""]; +} else { + [_this select 1] call FUNC(removeBISPFH); +}; \ No newline at end of file diff --git a/addons/frag/fnc_frago.sqf b/addons/frag/fnc_frago.sqf new file mode 100644 index 0000000000..88ec0c4742 --- /dev/null +++ b/addons/frag/fnc_frago.sqf @@ -0,0 +1,230 @@ +//fnc_frago.sqf +// #define DEBUG_MODE_FULL +#include "script_component.hpp" + +#define FRAG_VEC_VAR 0.004 + +#define MAX_FRAG_COUNT 50 + +if(!isServer) exitWith { }; + +// _startTime = diag_tickTime; +private ["_round", "_lastPos", "_lastVel", "_shellType", "_gun", "_fragTypes", "_warn", "_atlPos", "_isArmed", + "_fuseDist", "_indirectHitRange", "_fragRange", "_c", "_m", "_k", "_gC", "_fragPower", "_fragPowerRandom", + "_manObjects", "_objects", "_crew", "_fragCount", "_fragArcs", "_doRandom", "_target", "_boundingBox", + "_targetPos", "_distance", "_add", "_bbX", "_bbY", "_bbZ", "_cubic", "_targetVel", "_baseVec", "_dir", + "_currentCount", "_count", "_vecVar", "_i", "_vec", "_fp", "_vel", "_fragType", "_fragObj", "_randomCount", + "_sectorSize", "_sectorOffset", "_randomDir"]; + + +_round = _this select 0; +_lastPos = _this select 1; +_lastVel = _this select 2; +_shellType = _this select 3; +_gun = nil; +if((count _this) > 5) then { + _gun = _this select 5; +}; + +_fragTypes = [ + "ACE_frag_tiny", "ACE_frag_tiny", "ACE_frag_tiny", + "ACE_frag_tiny_HD", "ACE_frag_tiny_HD", "ACE_frag_tiny_HD", + "ACE_frag_small","ACE_frag_small","ACE_frag_small","ACE_frag_small", + "ACE_frag_small_HD","ACE_frag_small_HD","ACE_frag_small_HD","ACE_frag_small_HD", + "ACE_frag_medium_HD", "ACE_frag_medium_HD", "ACE_frag_medium_HD", "ACE_frag_medium_HD", "ACE_frag_medium_HD" + ]; + +_warn = false; +if(isArray (configFile >> "CfgAmmo" >> _shellType >> "ACE_frag_CLASSES")) then { + _fragTypes = getArray (configFile >> "CfgAmmo" >> _shellType >> "ACE_frag_CLASSES"); +} else { + _warn = true; +}; + +_atlPos = ASLtoATL _lastPos; + +_isArmed = true; +if(!isNil "_gun") then { + _fuseDist = getNumber(configFile >> "CfgAmmo" >> _shellType >> "fuseDistance"); + _isArmed = ((getPosASL _gun) distance _lastPos > _fuseDist); +}; + +_indirectHitRange = getNumber(configFile >> "CfgAmmo" >> _shellType >> "indirecthitrange"); +_fragRange = 20*_indirectHitRange*4; +// _c = 185; // grams of comp-b +// _m = 210; // grams of fragmentating metal +// _k = 3/5; // spherical K factor +// _gC = 2843; // Gurney constant of comp-b in /ms + +// _c = 429; // grams of tritonal +// _m = 496; // grams of fragmentating metal +// _k = 1/2; // spherical K factor +// _gC = 2320; // Gurney constant of tritonal in /ms + + +_c = getNumber(configFile >> "CfgAmmo" >> _shellType >> "ACE_frag_CHARGE"); +if(_c == 0) then { _c = 1; _warn = true;}; +_m = getNumber(configFile >> "CfgAmmo" >> _shellType >> "ACE_frag_METAL"); +if(_m == 0) then { _m = 2; _warn = true;}; +_k = getNumber(configFile >> "CfgAmmo" >> _shellType >> "ACE_frag_GURNEY_K"); +if(_k == 0) then { _k = 1/2; _warn = true;}; +_gC = getNumber(configFile >> "CfgAmmo" >> _shellType >> "ACE_frag_GURNEY_C"); +if(_gC == 0) then { _gC = 2440; _warn = true;}; + +if(_warn) then { + diag_log text format["Ammo class %1 lacks proper explosive properties definitions for frag!", _shellType]; //TODO: turn this off when we get closer to release +}; + +_fragPower = (((_m/_c)+_k)^-(1/2))*_gC; +_fragPower = _fragPower*0.8; // Gunery equation is for a non-fragmenting metal, imperical value of 80% represents fragmentation + +_fragPowerRandom = _fragPower*0.5; +if((_atlPos select 2) < 0.5) then { + _lastPos set[2, (_lastPos select 2)+0.5]; +}; + +// _manObjects = _atlPos nearEntities ["CaManBase", _fragRange]; + +// setAccTime 0.01; + +//_objects = nearestObjects [_atlPos, ["AllVehicles"], _fragRange]; // Not sure if tracking "ReammoBox" is required, if so revert this change for _objects +_objects = _atlPos nearEntities [["Car", "Motorcycle", "Tank", "StaticWeapon", "CAManBase", "Air", "Ship"], _fragRange]; + +// _objects = _manObjects; +// Target also people inside vehicles or manning weapons +_crew = []; +{ + { + _crew set [count _crew,_x] + } forEach (crew _x); +} forEach _objects; + +_objects = _objects - _crew; +_objects = _objects + _crew; + +_fragCount = 0; + +_fragArcs = []; +_fragArcs set[360, 0]; + +#ifdef DEBUG_MODE_FULL + player sideChat format["_fragRange: %1", _fragRange]; + player sideChat format["_objects: %1", _objects]; +#endif +_doRandom = false; +if(_isArmed && (count _objects) > 0) then { + { + //if(random(1) > 0.5) then { + _target = _x; + if(alive _target) then { + _boundingBox = boundingBox _target; + _targetPos = (getPosASL _target); + _distance = _targetPos distance _lastPos; + _add = (((_boundingBox select 1) select 2)/2)+((((_distance-(_fragpower/8)) max 0)/_fragPower)*10); + _bbX = (abs((_boundingBox select 0) select 0))+((_boundingBox select 1) select 0); + _bbY = (abs((_boundingBox select 0) select 1))+((_boundingBox select 1) select 1); + _bbZ = (abs((_boundingBox select 0) select 2))+((_boundingBox select 1) select 2); + _cubic = _bbX*_bbY*_bbZ; + if(_cubic > 1) then { + _doRandom = true; + + _targetVel = (velocity _target); + + _targetPos set[2, (_targetPos select 2)+_add]; + _targetPos set[0, (_targetPos select 0)+((_targetVel select 0)*(_distance/_fragPower))]; + _targetPos set[1, (_targetPos select 1)+((_targetVel select 1)*(_distance/_fragPower))]; + + _baseVec = [_lastPos, _targetPos] call BIS_fnc_vectorFromXToY; + + _dir = floor(_baseVec call CBA_fnc_vectDir); + _currentCount = _fragArcs select _dir; + if(isNil "_currentCount") then { + _currentCount = 0; + }; + if(_currentCount < 20) then { + _count = ceil(random(sqrt(_m/1000))); + _vecVar = FRAG_VEC_VAR; + if(!(_target isKindOf "Man")) then { + _vecVar = ((sqrt _cubic)/2000)+FRAG_VEC_VAR; + if((count (crew _target)) == 0 && _count > 0) then { + _count = 0 max (_count/2); + }; + }; + for "_i" from 1 to _count do { + _vec = +_baseVec; + + _vec set[0, (_vec select 0)-(_vecVar/2)+(random _vecVar)]; + _vec set[1, (_vec select 1)-(_vecVar/2)+(random _vecVar)]; + _vec set[2, (_vec select 2)-(_vecVar/2)+(random _vecVar)]; + + _fp = (_fragPower-(random (_fragPowerRandom))); + _vel = [ + (_vec select 0)*_fp, + (_vec select 1)*_fp, + (_vec select 2)*_fp + ]; + + _fragType = round (random ((count _fragTypes)-1)); + _fragObj = (_fragTypes select _fragType) createVehicleLocal [0,0,10000]; + // diag_log text format["fp: %1 %2", _fp, typeOf _fragObj]; + _fragObj setPosASL _lastPos; + _fragObj setVectorDir _vec; + _fragObj setVelocity _vel; + #ifdef DEBUG_MODE_FULL + GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1; + GVAR(traceFrags) = true; + #endif + if(GVAR(traceFrags)) then { + [player, _fragObj, [1,0,0,1]] call FUNC(addTrack); + }; + _fragCount = _fragCount + 1; + _currentCount = _currentCount + 1; + }; + _fragArcs set[_dir, _currentCount]; + }; + }; + }; + //}; + if(_fragCount > MAX_FRAG_COUNT) exitWith {}; + } forEach _objects; + if(_fragCount > MAX_FRAG_COUNT) exitWith {}; + _randomCount = (ceil((MAX_FRAG_COUNT-_fragCount)*0.1)) max 0; + _sectorSize = 360 / (_randomCount max 1); + // _doRandom = false; + if(_doRandom) then { + for "_i" from 1 to _randomCount do { + // Distribute evenly + _sectorOffset = 360 * (_i - 1) / (_randomCount max 1); + _randomDir = random(_sectorSize); + _vec = [cos(_sectorOffset + _randomDir), sin(_sectorOffset + _randomDir), sin(30 - (random 45))]; + + _fp = (_fragPower-(random (_fragPowerRandom))); + + _vel = [ + (_vec select 0)*_fp, + (_vec select 1)*_fp, + (_vec select 2)*_fp + ]; + + _fragType = round (random ((count _fragTypes)-1)); + _fragObj = (_fragTypes select _fragType) createVehicleLocal [0,0,10000]; + _fragObj setPosASL _lastPos; + _fragObj setVectorDir _vec; + _fragObj setVelocity _vel; + #ifdef DEBUG_MODE_FULL + GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1; + // [FUNC(frag_trace), 0, [_fragObj]] call cba_fnc_addPerFrameHandler; + GVAR(traceFrags) = true; + #endif + if(GVAR(traceFrags)) then { + [player, _fragObj, [1,0.5,0,1]] call FUNC(addTrack); + }; + _fragCount = _fragCount + 1; + }; + }; +}; +// #ifdef DEBUG_MODE_FULL + // player sideChat format["total frags: %1", GVAR(TOTALFRAGS)]; + // player sideChat format["tracks: %1", (count GVAR(trackedObjects))]; +// #endif +// _endTime = diag_tickTime; diff --git a/addons/frag/fnc_removeTrack.sqf b/addons/frag/fnc_removeTrack.sqf new file mode 100644 index 0000000000..b72830051a --- /dev/null +++ b/addons/frag/fnc_removeTrack.sqf @@ -0,0 +1,14 @@ +#include "script_component.hpp" + +private ["_ret"]; +_ret = true; +if(IS_ARRAY((_this select 0))) then { + _ret = false; +} else { + if((_this select 0) in GVAR(trackedObjects)) then { + GVAR(trackedObjects) = GVAR(trackedObjects) - [(_this select 0)]; + } else { + _ret = false; + }; +}; +_ret \ No newline at end of file diff --git a/addons/frag/fnc_spallHP.sqf b/addons/frag/fnc_spallHP.sqf new file mode 100644 index 0000000000..aeba4e7a5d --- /dev/null +++ b/addons/frag/fnc_spallHP.sqf @@ -0,0 +1,29 @@ +#include "script_component.hpp" + +private ["_initialData", "_currentCount", "_hpData", "_round", "_hpRound"]; +//player sideChat format["f: %1 c: %2", (_this select 0), (count GVAR(spallHPData))]; +if((_this select 0) <= (count GVAR(spallHPData))) then { + _initialData = GVAR(spallHPData) select (_this select 0); + if(!isNil "_initialData") then { + _hpRound = ((_this select 1) select 0) select 2; + _round = _initialData select 3; + _hpDirect = ((_this select 1) select 0) select 10; + if(_hpDirect && {_round == _hpRound}) then { + + { + _hpData = _x; + _round = _initialData select 3; + // diag_log text format["HPDUMP-------------------------------------"]; + // { + // _hp = _x; + // diag_log text format["%1 --", _forEachIndex]; + // { + // diag_log text format["%1: %2", _forEachIndex, _x]; + // } forEach _hp; + // } forEach (_this select 1); + [FUNC(doSpall), 0, [_this, _forEachIndex]] call cba_fnc_addPerFrameHandler; + // player sideChat "WEEE"; + } forEach (_this select 1); + }; + }; +}; \ No newline at end of file diff --git a/addons/frag/fnc_spallTrack.sqf b/addons/frag/fnc_spallTrack.sqf new file mode 100644 index 0000000000..31e9c228bb --- /dev/null +++ b/addons/frag/fnc_spallTrack.sqf @@ -0,0 +1,40 @@ +//fnc_spallTrack.sqf +#include "script_component.hpp" +private ["_params", "_round", "_multiplier", "_delta", "_curPos", "_velocity", "_velocityStep", "_forwardPos", "_intersectsWith", "_index", "_i", "_test", "_hpId", "_data"]; +// setAccTime 0; +_round = _this select 0; +_multiplier = _this select 1; +_foundObjects = _this select 2; +_foundObjectHPIds = _this select 3; + +_delta = (1/diag_fps)*_multiplier; +_curPos = getPosASL _round; +_velocity = velocity _round; + +_velocityStep = [ + (_velocity select 0)*_delta, + (_velocity select 1)*_delta, + (_velocity select 2)*_delta + ]; +_forwardPos = [ + (_curPos select 0) + (_velocityStep select 0), + (_curPos select 1) + (_velocityStep select 1), + (_curPos select 2) + (_velocityStep select 2) + ]; + +_intersectsWith = lineIntersectsWith [_curPos, _forwardPos]; + +if(count _intersectsWith > 0) then { + // player sideChat format["inter: %1", _intersectsWith]; + { + if(!(_x in _foundObjects)) then { + // diag_log text format["Adding HP: %1", _x]; + _index = (count GVAR(spallHPData)); + _hpId = _x addEventHandler ["hitPart", format["[%1, _this] call " + QUOTE(FUNC(spallHP)), _index]]; + _foundObjects set[(count _foundObjects), _x]; + _foundObjectHPIds set[(count _foundObjectHPIds), _hpId]; + _data = [_hpId, _x, typeOf _round, _round, _curPos, _velocity, 0, _foundObjects, _foundObjectHPIds]; + GVAR(spallHPData) set[_index, _data]; + }; + } forEach _intersectsWith; +}; \ No newline at end of file diff --git a/addons/frag/fnc_startTracing.sqf b/addons/frag/fnc_startTracing.sqf new file mode 100644 index 0000000000..31f4b99762 --- /dev/null +++ b/addons/frag/fnc_startTracing.sqf @@ -0,0 +1,5 @@ +#include "script_component.hpp" +if(!GVAR(tracesStarted)) then { + GVAR(tracesStarted) = true; + GVAR(traceID) = [FUNC(drawTraces), 0, []] call cba_fnc_addPerFrameHandler; +}; \ No newline at end of file diff --git a/addons/frag/fnc_stopTracing.sqf b/addons/frag/fnc_stopTracing.sqf new file mode 100644 index 0000000000..02b4fd7f59 --- /dev/null +++ b/addons/frag/fnc_stopTracing.sqf @@ -0,0 +1,5 @@ +#include "script_component.hpp" +if(GVAR(tracesStarted)) then { + GVAR(tracesStarted) = false; + [GVAR(traceID)] call FUNC(removeBISPFH); +}; \ No newline at end of file diff --git a/addons/frag/fnc_trackFragRound.sqf b/addons/frag/fnc_trackFragRound.sqf new file mode 100644 index 0000000000..2780a85664 --- /dev/null +++ b/addons/frag/fnc_trackFragRound.sqf @@ -0,0 +1,52 @@ +//fnc_trackFragRound.sqf +#include "script_component.hpp" +private ["_params", "_round", "_lastPos", "_lastVel", "_type", "_time", "_doSpall", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"]; +_params = _this select 0; +_round = _params select 0; +_lastPos = _params select 1; +_lastVel = _params select 2; +_type = _params select 3; +_time = _params select 4; +_doSpall = _params select 6; +_spallTrack = _params select 7; +_foundObjectHPIds = _params select 8; + +if (!alive _round) then { + [_this select 1] call FUNC(removeBISPFH); + if(_time != time && {_round in GVAR(trackedObjects)} && {!(_round in GVAR(blackList))}) then { + GVAR(trackedObjects) = GVAR(trackedObjects) - [_round]; + _skip = getNumber (configFile >> "CfgAmmo" >> _type >> "ACE_FRAG_SKIP"); + if(_skip == 0) then { + _explosive = getNumber (configFile >> "CfgAmmo" >> _type >> "explosive"); + _indirectRange = getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange"); + _force = getNumber (configFile >> "CfgAmmo" >> _type >> "ACE_FRAG_FORCE"); + _fragPower = getNumber(configFile >> "CfgAmmo" >> _type >> "indirecthit")*(sqrt(_indirectRange)); + if((_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}) || {_force == 1} ) then { + [QGVAR(frag_eh), _params] call CBA_fnc_clientToServerEvent; + GVAR(trackedObjects) = GVAR(trackedObjects) - [_round]; + }; + }; + }; + if(_doSpall) then { + GVAR(spallIsTrackingCount) = GVAR(spallIsTrackingCount) - 1; + // diag_log text format["F: %1", _foundObjectHPIds]; + { + if(!isNil "_x") then { + _x removeEventHandler ["hitPart", _foundObjectHPIds select _forEachIndex]; + }; + } forEach _spallTrack; + }; +} else { + if(!(_round in GVAR(trackedObjects)) || {_round in GVAR(blackList)}) then { + [_this select 1] call FUNC(removeBISPFH); + if(_round in GVAR(blackList)) then { + GVAR(blackList) = GVAR(blackList) - [_round]; + }; + }; + + _params set[1, (getPosASL _round)]; + _params set[2, (velocity _round)]; + if(_doSpall) then { + [_round, 1, _spallTrack, _foundObjectHPIds] call FUNC(spallTrack); + }; +}; diff --git a/addons/frag/fnc_trackTrace.sqf b/addons/frag/fnc_trackTrace.sqf new file mode 100644 index 0000000000..71b4a9a866 --- /dev/null +++ b/addons/frag/fnc_trackTrace.sqf @@ -0,0 +1,14 @@ +#include "script_component.hpp" +_params = _this select 0; +_tracerObj = _params select 0; +_index = _params select 1; + +if(alive _tracerObj && (count GVAR(traces)) > 0) then { + _data = GVAR(traces) select _index; + _positions = _data select 4; + _objVel = velocity _tracerObj; + _objTVel = sqrt((_objVel select 0)^2 + (_objVel select 1)^2 + (_objVel select 2)^2); + _positions set[(count _positions), [(getPos _tracerObj), _objTVel]]; +} else { + [(_this select 1)] call FUNC(removeBISPFH); +}; \ No newline at end of file diff --git a/addons/frag/fnc_vectorDiffFast.sqf b/addons/frag/fnc_vectorDiffFast.sqf new file mode 100644 index 0000000000..0a41860727 --- /dev/null +++ b/addons/frag/fnc_vectorDiffFast.sqf @@ -0,0 +1,15 @@ +#include "script_component.hpp" +private["_p1","_p2","_return"]; + +_p1 = _this select 0; +_p2 = _this select 1; + +if ((count _p1) != (count _p2)) then {textLogFormat ["BIS_FNC Error: vectors not of same size"]}; + +_return = []; + +{ + _return set[_forEachIndex, (_p2 select _forEachIndex) - _x]; +} forEach _p1; + +_return diff --git a/addons/frag/script_component.hpp b/addons/frag/script_component.hpp new file mode 100644 index 0000000000..274270cbbb --- /dev/null +++ b/addons/frag/script_component.hpp @@ -0,0 +1,14 @@ +#define COMPONENT frag +#include "\z\ace\Addons\main\script_mod.hpp" + +#define DEBUG_ENABLED_FRAG + +#ifdef DEBUG_ENABLED_FRAG + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_FRAG + #define DEBUG_SETTINGS DEBUG_SETTINGS_FRAG +#endif + +#include "\z\ace\Addons\main\script_macros.hpp" \ No newline at end of file diff --git a/addons/frag/stringtable.xml b/addons/frag/stringtable.xml new file mode 100644 index 0000000000..f3562ee5b1 --- /dev/null +++ b/addons/frag/stringtable.xml @@ -0,0 +1,18 @@ + + + + + +(Æ) Disable Fragmentation +(Æ) Zakázat fragmentaci granátů +(Æ) Weapons: Keine Schrapnelle +(Æ) Wyłącz głowice fragmentacyjne +(Æ) Выключить разлёт осколков +(Æ) Disable Fragmentation +(Æ) Disable Fragmentation +(Æ) Disable Fragmentation +(Æ) Disable Fragmentation + + + + diff --git a/addons/laser/$PBOPREFIX$ b/addons/laser/$PBOPREFIX$ new file mode 100644 index 0000000000..1e4e48a4ca --- /dev/null +++ b/addons/laser/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\Addons\laser \ No newline at end of file diff --git a/addons/laser/CfgEventhandlers.hpp b/addons/laser/CfgEventhandlers.hpp new file mode 100644 index 0000000000..1fcfc0244f --- /dev/null +++ b/addons/laser/CfgEventhandlers.hpp @@ -0,0 +1,11 @@ +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_pre_init)); + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_post_init)); + }; +}; diff --git a/addons/laser/CfgVehicles.hpp b/addons/laser/CfgVehicles.hpp new file mode 100644 index 0000000000..1c5887bd38 --- /dev/null +++ b/addons/laser/CfgVehicles.hpp @@ -0,0 +1,9 @@ +class CfgVehicles { + class All; + + class LaserTarget: All { + class EventHandlers { + init = QUOTE(_this call FUNC(laser_init)); + }; + }; +}; \ No newline at end of file diff --git a/addons/laser/XEH_post_init.sqf b/addons/laser/XEH_post_init.sqf new file mode 100644 index 0000000000..6904ee6c47 --- /dev/null +++ b/addons/laser/XEH_post_init.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" +NO_DEDICATED; + diff --git a/addons/laser/XEH_pre_init.sqf b/addons/laser/XEH_pre_init.sqf new file mode 100644 index 0000000000..8a4b3166b8 --- /dev/null +++ b/addons/laser/XEH_pre_init.sqf @@ -0,0 +1,26 @@ +#include "script_component.hpp" + +PREP(rotateVectLineGetMap); +PREP(rotateVectLine); +PREP(shootRay); +PREP(shootCone); +PREP(checkLos); + +PREP(findLaserDesignator); +PREP(findStrongestRay); + +PREP(translateToModelSpace); +PREP(translateToWeaponSpace); + +PREP(laser_init); + +GVAR(laser) = nil; // a single hud draws 1 laser at a time + +PREP(laserTargetPFH); + +ACE_LASERS = []; + +ACE_DEFAULT_LASER_CODE = 1000; +ACE_DEFAULT_FIRE_SELECTION = [FIREMODE_DIRECT_LOAL, ACE_DEFAULT_LASER_CODE]; + +FUNC(getPosASL) = {visiblePositionASL (_this select 0)}; \ No newline at end of file diff --git a/addons/laser/config.cpp b/addons/laser/config.cpp new file mode 100644 index 0000000000..ee1b9f1996 --- /dev/null +++ b/addons/laser/config.cpp @@ -0,0 +1,14 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { "uo_main", "a3_ui_f" }; + version = VERSION; + }; +}; + +#include "CfgEventhandlers.hpp" +#include "CfgVehicles.hpp" \ No newline at end of file diff --git a/addons/laser/fnc_checkLos.sqf b/addons/laser/fnc_checkLos.sqf new file mode 100644 index 0000000000..f0df153887 --- /dev/null +++ b/addons/laser/fnc_checkLos.sqf @@ -0,0 +1,31 @@ +#include "script_component.hpp" + +private ["_pos1", "_pos2", "_spacing", "_vectorTo", "_x", "_y", "_z", "_distance", "_count", "_return", "_alt", "_pos", "_designator", "_seeker"]; +_pos1 = _this select 0; +_pos2 = _this select 1; +_designator = _this select 2; +_seeker = _this select 3; +_spacing = 100; +if((count _this) > 4) then { + _spacing = _this select 4; +}; + +_return = true; +_vectorTo = [_pos2, _pos1] call BIS_fnc_vectorFromXToY; + +_x = (_vectorTo select 0)*0.25; +_y = (_vectorTo select 1)*0.25; +_z = (_vectorTo select 2)*0.25; + +_pos2 = [(_pos2 select 0) + _x, (_pos2 select 1) + _y, (_pos2 select 2) + _z]; + +// player sideChat format["new los check"]; +if(terrainIntersect [_pos2, _pos1]) then { + _return = false; +} else { + if(lineIntersects [_pos2, _pos1]) then { // should take as arguments and add to this command objects to exclude - target and observer + // player sideChat format["with: %1", lineIntersectsWith [_pos1, _pos2]]; + _return = false; + }; +}; +_return; \ No newline at end of file diff --git a/addons/laser/fnc_findLaserDesignator.sqf b/addons/laser/fnc_findLaserDesignator.sqf new file mode 100644 index 0000000000..8a2e4caf29 --- /dev/null +++ b/addons/laser/fnc_findLaserDesignator.sqf @@ -0,0 +1,70 @@ +#include "script_component.hpp" + +private ["_missile", "_headingPitch", "_found", "_vectorTo", "_polarTo", "_dir", "_vertOk", "_horzOk", "_fov", + "_closestDistance", "_pos1", "_pos2", "_disCheck", "_currentTarget", "_potentialTargets", "_offset", "_vector"]; +_missile = _this select 0; +_laserCode = _this select 1; +_fov = if (count _this > 2) then {_this select 2} else {75}; +_vector = if (count _this > 3) then {_this select 3} else {vectorDir _missile}; +_offset = if (count _this > 4) then {_this select 4} else {[0,0,0]}; + +_headingPitch = _vector call CBA_fnc_vect2polar; +_currentTarget = nil; +_found = false; + +LOG("Searching lasers"); +if(!(isNil "ACE_LASERS")) then { + _potentialTargets = []; + TRACE_1("", ACE_LASERS); + + { + if(!(isNull _x)) then { + _sensorPos = ATLtoASL(_missile modelToWorld _offset); + _vectorTo = [_sensorPos, ([_x] call FUNC(getPosASL))] call BIS_fnc_vectorFromXToY; + _polarTo = _vectorTo call CBA_fnc_vect2polar; + _dir = _polarTo select 1; + _dir = _dir - (_headingPitch select 1); + + TRACE_4("Calc", _sensorPos, _vectorTo, _polarTo, _dir); + + if (_dir < 0) then {_dir = _dir + 360}; + if (_dir > 360) then {_dir = _dir - 360}; + _vertOk = false; + _horzOk = false; + if(_dir < _fov || {_dir > (360-_fov)}) then { + _horzOk = true; + }; + if(abs((abs(_polarTo select 2))-(abs(_headingPitch select 2))) < _fov) then { + _vertOk = true; + }; + + TRACE_2("Results", _vertOk, _horzOk); + + if(_vertOk && {_horzOk}) then { + // Does the laser currently have our current code, if we have one? + _targetCode = _x getVariable ["ACE_LASERTARGET_CODE", ACE_DEFAULT_LASER_CODE]; + TRACE_1("Target in sight, checking code", _targetCode, _laserCode); + if(_targetCode == _laserCode) then { + _potentialTargets set[(count _potentialTargets), _x]; + }; + }; + }; + + } forEach ACE_LASERS; + + TRACE_1("", _potentialTargets); + + _closestDistance = 100000; + { + _pos1 = (getPosASL _missile); + _pos2 = ([_x] call FUNC(getPosASL)); + _disCheck = _pos1 distance _pos2; + // shouldn't this bail out when a valid target is found instead of iterating over all potential targets ? + if(_disCheck < _closestDistance && {[_pos1, _pos2, _x, _missile] call FUNC(checkLos)}) then { + _found = true; + _currentTarget = _x; + _closestDistance = _disCheck; + }; + } forEach _potentialTargets; +}; +[_found, _currentTarget] \ No newline at end of file diff --git a/addons/laser/fnc_findStrongestRay.sqf b/addons/laser/fnc_findStrongestRay.sqf new file mode 100644 index 0000000000..db85ce8b3d --- /dev/null +++ b/addons/laser/fnc_findStrongestRay.sqf @@ -0,0 +1,49 @@ +#include "script_component.hpp" + +_list = _this select 0; +_checkPos = _this select 1; +_spots = []; +_outliers = []; +_spot = []; +_testPos = (_list select 0) select 0; +{ + _samplePos = _x select 0; + if(!lineIntersects [_samplePos, _checkPos] && {!terrainIntersectASL [_samplePos, _checkPos]}) then { + if(_samplePos distance _testPos < 2) then { + _spot pushBack _samplePos; + } else { + _outliers pushBack _samplePos; + }; + }; +} forEach _list; +_spots pushBack _spot; + +if(count _outliers > 0) then { + for "_i" from 1 to 3 do { + _remainingSpots = _outliers; + _outliers = []; + _spot = []; + _testPos = (_remainingSpots select 0); + { + _samplePos = _x; + if(!lineIntersects [_samplePos, _checkPos] && {!terrainIntersectASL [_samplePos, _checkPos]}) then { + if(_samplePos distance _testPos < 2) then { + _spot pushBack _samplePos; + } else { + _outliers pushBack _samplePos; + }; + }; + } forEach _remainingSpots; + _spots pushBack _spot; + }; +}; +_largest = 0; +_largestSpot = []; +{ + if((count _x) > _largest) then { + _largest = (count _x); + _largestSpot = _x; + }; +} forEach _spots; +// player sideChat format["g: %1", _spots]; +_largestSpot select (random (floor(count _largestSpot))); \ No newline at end of file diff --git a/addons/laser/fnc_laserTargetPFH.sqf b/addons/laser/fnc_laserTargetPFH.sqf new file mode 100644 index 0000000000..bf526f464e --- /dev/null +++ b/addons/laser/fnc_laserTargetPFH.sqf @@ -0,0 +1,26 @@ +#include "script_component.hpp" + +private["_args", "_laserTarget"]; +//TRACE_1("enter", _this); +_args = _this select 0; +_laserTarget = _args select 0; + +if(isNull _laserTarget || !alive player) exitWith { + [(_this select 1)] call cba_fnc_removePerFrameHandler; + REM(ACE_LASERS, _laserTarget); +}; + +_end = diag_tickTime; + +#ifdef DEBUG_MODE_FULL +// Iconize the location of the actual laserTarget +_pos = [_laserTarget] call FUNC(getPosASL); +drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [1,0,0,1], (ASLtoATL _pos), 0.75, 0.75, 0, "", 0.5, 0.025, "TahomaB"]; + +{ + drawLine3D [ASLtoATL (_x select 0), ASLtoATL (_x select 1), (_x select 2)]; + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", (_x select 2), ASLtoATL (_x select 1), 0.75, 0.75, 0, "", 0.5, 0.025, "TahomaB"]; +} forEach DRAW_LINES; +DRAW_LINES = []; +#endif + diff --git a/addons/laser/fnc_laser_init.sqf b/addons/laser/fnc_laser_init.sqf new file mode 100644 index 0000000000..4c6b0b5f2a --- /dev/null +++ b/addons/laser/fnc_laser_init.sqf @@ -0,0 +1,25 @@ +#include "script_component.hpp" +PARAMS_1(_laserTarget); + +TRACE_1("enter", _this); + +// Add the target to the global targets array +// Everyone tracks them + +// Add the laser localized to the laser array, and give it the default localized code +PUSH(ACE_LASERS, _laserTarget); +// Check the vehicle, otherwise use the default +_laserTarget setVariable ["ACE_LASERTARGET_CODE", ACE_DEFAULT_LASER_CODE, false]; +// Clean the lasers of any null objects while we are here +REM(ACE_LASERS, objNull); + +if(!(local _laserTarget)) exitWith { }; +// The target is local, so its on this client +if(!isDedicated) then { + _laserTarget setVariable ["ACE_LASERTARGET_SHOOTER", player, true]; + + [FUNC(laserTargetPFH), 0, [_laserTarget, player]] call cba_fnc_addPerFrameHandler; +} else { + // server side ownership of laser + //_laserTarget setVariable ["ACE_LASERTARGET_SHOOTER", nil, false]; +}; diff --git a/addons/laser/fnc_rotateVectLine.sqf b/addons/laser/fnc_rotateVectLine.sqf new file mode 100644 index 0000000000..b0360cc330 --- /dev/null +++ b/addons/laser/fnc_rotateVectLine.sqf @@ -0,0 +1,38 @@ +#include "script_component.hpp" + +_map = _this select 0; +_theta = _this select 1; + +_p = _map select 0; +_p1 = _map select 1; +_p2 = _map select 2; + +_q1 = +(_map select 3); +_q2 = +(_map select 4); +_u = _map select 5; +_d = _map select 6; + +/* Step 4 */ +_q2 set[0, (_q1 select 0) * cos(_theta) - (_q1 select 1) * sin(_theta)]; +_q2 set[1, (_q1 select 0) * sin(_theta) + (_q1 select 1) * cos(_theta)]; +_q2 set[2, (_q1 select 2)]; + +/* Inverse of step 3 */ +_q1 set[0, (_q2 select 0) * _d + (_q2 select 2) * (_u select 0)]; +_q1 set[1, (_q2 select 1)]; +_q1 set[2, - (_q2 select 0) * (_u select 0) + (_q2 select 2) * _d]; + +/* Inverse of step 2 */ +if (_d != 0) then { + _q2 set[0, (_q1 select 0)]; + _q2 set[1, (_q1 select 1) * (_u select 2) / _d + (_q1 select 2) * (_u select 1) / _d]; + _q2 set[2, - (_q1 select 1) * (_u select 1) / _d + (_q1 select 2) * (_u select 2) / _d]; +} else { + _q2 = _q1; +}; + +/* Inverse of step 1 */ +_q1 set[0, (_q2 select 0) + (_p1 select 0)]; +_q1 set[1, (_q2 select 1) + (_p1 select 1)]; +_q1 set[2, (_q2 select 2) + (_p1 select 2)]; +_q1; \ No newline at end of file diff --git a/addons/laser/fnc_rotateVectLineGetMap.sqf b/addons/laser/fnc_rotateVectLineGetMap.sqf new file mode 100644 index 0000000000..fdbd6533ef --- /dev/null +++ b/addons/laser/fnc_rotateVectLineGetMap.sqf @@ -0,0 +1,37 @@ +#include "script_component.hpp" + +private ["_p", "_theta", "_p1", "_p2", "_q1", "_q2", "_u", "_d"]; +_p = _this select 0; +_p1 = _this select 1; +_p2 = _this select 2; + +_q1 = []; +_q2 = []; +_u = []; + +/* Step 1 */ +_q1 set[0, (_p select 0) - (_p1 select 0)]; +_q1 set[1, (_p select 1) - (_p1 select 1)]; +_q1 set[2, (_p select 2) - (_p1 select 2)]; + +_u set[0, (_p2 select 0) - (_p1 select 0)]; +_u set[1, (_p2 select 1) - (_p1 select 1)]; +_u set[2, (_p2 select 2) - (_p1 select 2)]; +_u = _u call BIS_fnc_unitVector; +_d = sqrt((_u select 1)*(_u select 1) + (_u select 2)*(_u select 2)); + +/* Step 2 */ +if (_d != 0) then { + _q2 set[0, (_q1 select 0)]; + _q2 set[1, (_q1 select 1) * (_u select 2) / _d - (_q1 select 2) * (_u select 1) / _d]; + _q2 set[2, (_q1 select 1) * (_u select 1) / _d + (_q1 select 2) * (_u select 2) / _d]; +} else { + _q2 = _q1; +}; + +/* Step 3 */ +_q1 set[0, (_q2 select 0) * _d - (_q2 select 2) * (_u select 0)]; +_q1 set[1, (_q2 select 1)]; +_q1 set[2, (_q2 select 0) * (_u select 0) + (_q2 select 2) * _d]; + +[_p, _p1, _p2, _q1, _q2, _u, _d] \ No newline at end of file diff --git a/addons/laser/fnc_shootCone.sqf b/addons/laser/fnc_shootCone.sqf new file mode 100644 index 0000000000..8d2d7fef66 --- /dev/null +++ b/addons/laser/fnc_shootCone.sqf @@ -0,0 +1,66 @@ +#include "script_component.hpp" + +_divergence = 0.3; +_pos = _this select 0; +_vec = _this select 1; +_longestReturn = -1000000000; +_shortestReturn = 1000000000; +_resultPositions = []; +_p1 = [0,0,0]; +_p2 = +_vec; +_p = (_vec call CBA_fnc_vect2polar); +_v = [(_p select 0), (_p select 1), (_p select 2)+90] call CBA_fnc_polar2vect; +_cp = [_vec, _v] call BIS_fnc_crossProduct; + +_vecRotateMap = [_cp, _p1, _p2] call FUNC(rotateVectLineGetMap); + +_result = [_pos, _vec] call FUNC(shootRay); +_resultPos = _result select 0; +if(!isNil "_resultPos") then { + _distance = _result select 1; + if(_distance < _shortestReturn) then { + _shortestReturn = _distance; + }; + if(_distance > _longestReturn) then { + _longestReturn = _distance; + }; + _resultPositions set[(count _resultPositions), _result]; +#ifdef DEBUG_MODE_FULL + DRAW_LINES set[(count DRAW_LINES), [_pos, _resultPos, [0, 1, 0, 1]]]; +#endif +}; +_count = 8; + +_pos2 = [ + (_pos select 0)+((_vec select 0)*1000), + (_pos select 1)+((_vec select 1)*1000), + (_pos select 2)+((_vec select 2)*1000) + ]; +{ + for "_i" from 0 to ceil(_count*_x) do { + _radOffset = random 360; + _offset = [_vecRotateMap, (((360/_count)*_i)+_radOffset) mod 360] call FUNC(rotateVectLine); + _offsetPos = [ + (_pos2 select 0)+((_offset select 0)*(_divergence*_x)), + (_pos2 select 1)+((_offset select 1)*(_divergence*_x)), + (_pos2 select 2)+((_offset select 2)*(_divergence*_x)) + ]; + _offsetVector = [_pos, _offsetPos] call BIS_fnc_vectorFromXtoY; + _result = [_pos, _offsetVector] call FUNC(shootRay); + _resultPos = _result select 0; + if(!isNil "_resultPos") then { + _distance = _result select 1; + if(_distance < _shortestReturn) then { + _shortestReturn = _distance; + }; + if(_distance > _longestReturn) then { + _longestReturn = _distance; + }; + _resultPositions set[(count _resultPositions), _result]; +#ifdef DEBUG_MODE_FULL + DRAW_LINES set[(count DRAW_LINES), [_pos, _resultPos, [0, 1, 0, 1]]]; +#endif + }; + }; +} forEach [1,0.5,0.25]; +[_longestReturn, _shortestReturn, _resultPositions]; \ No newline at end of file diff --git a/addons/laser/fnc_shootRay.sqf b/addons/laser/fnc_shootRay.sqf new file mode 100644 index 0000000000..768194e351 --- /dev/null +++ b/addons/laser/fnc_shootRay.sqf @@ -0,0 +1,30 @@ +#include "script_component.hpp" + +private ["_pos", "_vec", "_distance", "_resultPos", "_fidelity", "_lastPos", "_i", "_nextPos"]; +scopeName "main"; +_pos = _this select 0; +_vec = _this select 1; +_distance = 0; +_resultPos = nil; +_fidelity = [1000,100,10,1,0.1]; +_lastPos = +_pos; +{ + scopeName "mainSearch"; + for "_i" from 1 to 10 do { + _nextPos = [ + (_lastPos select 0)+((_vec select 0)*_x), + (_lastPos select 1)+((_vec select 1)*_x), + (_lastPos select 2)+((_vec select 2)*_x) + ]; + + if(lineIntersects [_lastPos, _nextPos] || terrainIntersectASL [_lastPos, _nextPos]) then { + _resultPos = _lastPos; + breakTo "mainSearch"; + } else { + _distance = _distance + _x; + _lastPos = _nextPos; + }; + }; + +} forEach _fidelity; +[_resultPos, _distance]; \ No newline at end of file diff --git a/addons/laser/fnc_translateToModelSpace.sqf b/addons/laser/fnc_translateToModelSpace.sqf new file mode 100644 index 0000000000..1e2e930ac7 --- /dev/null +++ b/addons/laser/fnc_translateToModelSpace.sqf @@ -0,0 +1,16 @@ +_object = _this select 0; +_origin = getPosASL _object; +_matrix = _this select 1; +_xVec = _matrix select 0; +_yVec = _matrix select 1; +_zVec = _matrix select 2; + +_offset = _this select 2; + +_x = _offset select 0; +_y = _offset select 1; +_z = _offset select 2; + +_out = (((_xVec vectorMultiply _x) vectorAdd (_yVec vectorMultiply _y)) vectorAdd (_zVec vectorMultiply _z)) vectorAdd _origin; + +_out; \ No newline at end of file diff --git a/addons/laser/fnc_translateToWeaponSpace.sqf b/addons/laser/fnc_translateToWeaponSpace.sqf new file mode 100644 index 0000000000..406d81b145 --- /dev/null +++ b/addons/laser/fnc_translateToWeaponSpace.sqf @@ -0,0 +1,22 @@ +_object = _this select 0; +_origin = getPosASL _object; +_matrix = _this select 1; +_xVec = _matrix select 0; +_yVec = _matrix select 1; +_zVec = _matrix select 2; + +_offset = _this select 2; + +_offset = _offset vectorDiff _origin; + +_x = _offset select 0; +_y = _offset select 1; +_z = _offset select 2; + +_out = [ + ((_xVec select 0)*_x) + ((_xVec select 1)*_y) + ((_xVec select 2)*_z), + ((_yVec select 0)*_x) + ((_yVec select 1)*_y) + ((_yVec select 2)*_z), + ((_zVec select 0)*_x) + ((_zVec select 1)*_y) + ((_zVec select 2)*_z) + ]; + +_out; \ No newline at end of file diff --git a/addons/laser/script_component.hpp b/addons/laser/script_component.hpp new file mode 100644 index 0000000000..afca689204 --- /dev/null +++ b/addons/laser/script_component.hpp @@ -0,0 +1,15 @@ +#define COMPONENT laser +#include "\z\ace\Addons\main\script_mod.hpp" + +#ifdef DEBUG_ENABLED_LASER + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_LASER + #define DEBUG_SETTINGS DEBUG_SETTINGS_LASER +#endif + +#include "\z\ace\Addons\main\script_macros.hpp" + + +#define FIREMODE_DIRECT_LOAL 1 \ No newline at end of file diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index fb3136e852..5f1b50c61d 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -100,7 +100,7 @@ #define ACE_BWC ace_bwc = 1 -#define ACE_wind ([] call ace_sys_ballistic_fnc_wind) +#define ACE_wind ([] call ace_ballistic_fnc_wind) // SCRIPTING MACROS @@ -130,7 +130,7 @@ #define RING ace_common_fx_fnc_ring // Stamina -#define INC_MASS ace_sys_stamina_fnc_inc_mass +#define INC_MASS ace_stamina_fnc_inc_mass // Does this work, due to BWC_CONFIG(NAME) ? #undef BWC_CONFIG diff --git a/addons/main/script_macros_menudef.hpp b/addons/main/script_macros_menudef.hpp index 3572092852..35a8e2be45 100644 --- a/addons/main/script_macros_menudef.hpp +++ b/addons/main/script_macros_menudef.hpp @@ -2,7 +2,7 @@ // Self Interaction Menu not available if player is unconscious #define ACE_INTERACT_ALIVE (alive player) -#define ACE_INTERACT_UNCON (player call ace_sys_wounds_fnc_isUncon) +#define ACE_INTERACT_UNCON (player call ace_wounds_fnc_isUncon) // Player is Player Vehicle #define ACE_INTERACT_PLAYER (player == vehicle player || (player != vehicle player && player in assignedCargo vehicle player)) @@ -21,7 +21,7 @@ #define ACE_ASSEMBLE (getNumber(configFile >> "CfgActions" >> "Assemble" >> "show") == 0) #define ACE_DISASSEMBLE (getNumber(configFile >> "CfgActions" >> "DisAssemble" >> "show") == 0) #define ACE_PIPEDEFAULT (getNumber(configFile >> "CfgMagazines" >> "PipeBomb" >> "useAction") == 0) -#define ACE_IDENTITYDEFAULT (isClass(configFile >> "CfgPatches" >> "ace_sys_combatdeaf")) -#define ACE_RUCKDEFAULT (isClass(configFile >> "CfgPatches" >> "ace_sys_stamina")) +#define ACE_IDENTITYDEFAULT (isClass(configFile >> "CfgPatches" >> "ace_combatdeaf")) +#define ACE_RUCKDEFAULT (isClass(configFile >> "CfgPatches" >> "ace_stamina")) -#define ACE_KNOWN2PLAYER (if (name _target in (player getVariable ["ace_sys_recognize_knownnames",[]])) then { name _target } else { " " }) \ No newline at end of file +#define ACE_KNOWN2PLAYER (if (name _target in (player getVariable ["ace_recognize_knownnames",[]])) then { name _target } else { " " }) \ No newline at end of file diff --git a/addons/main/script_mod.hpp b/addons/main/script_mod.hpp index ed2b6ae87c..c8dfd56b4c 100644 --- a/addons/main/script_mod.hpp +++ b/addons/main/script_mod.hpp @@ -17,39 +17,39 @@ #define REQUIRED_VERSION 0.5 /* - #define DEBUG_ENABLED_SYS_ADDONS - #define DEBUG_ENABLED_SYS_ATTACHMENTS - #define DEBUG_ENABLED_sys_weapons_backblast - #define DEBUG_ENABLED_SYS_BLOOD - #define DEBUG_ENABLED_SYS_CARTRIDGES - #define DEBUG_ENABLED_SYS_CRATERS - #define DEBUG_ENABLED_SYS_CREWPROTECTION - #define DEBUG_ENABLED_SYS_DUMMIES - #define DEBUG_ENABLED_SYS_EJECT - #define DEBUG_ENABLED_SYS_EXPLOSIVES - #define DEBUG_ENABLED_SYS_FLARES - #define DEBUG_ENABLED_SYS_FLASHBANG - #define DEBUG_ENABLED_SYS_GRENADETHROW - #define DEBUG_ENABLED_SYS_HUNTIR - #define DEBUG_ENABLED_SYS_INTERACTION - #define DEBUG_ENABLED_SYS_IRSTROBE - #define DEBUG_ENABLED_SYS_MULTI_BARREL - #define DEBUG_ENABLED_SYS_MUZZLEBLAST - #define DEBUG_ENABLED_SYS_NVG - #define DEBUG_ENABLED_sys_weapons_overheating - #define DEBUG_ENABLED_SYS_RECOILDUST - #define DEBUG_ENABLED_SYS_ROCKET_BALLISTICS - #define DEBUG_ENABLED_SYS_SANDBAG - #define DEBUG_ENABLED_SYS_SHOTGUN - #define DEBUG_ENABLED_SYS_SIGHT_ADJUSTMENT_AT - #define DEBUG_ENABLED_SYS_SIGHT_ADJUSTMENT_GL - #define DEBUG_ENABLED_SYS_SIGHT_ADJUSTMENT_RIFLE - #define DEBUG_ENABLED_SYS_SMAW_SPOTTINGRIFLE - #define DEBUG_ENABLED_SYS_TRACERS - #define DEBUG_ENABLED_SYS_TRACKING - #define DEBUG_ENABLED_SYS_VIEWBLOCK - #define DEBUG_ENABLED_SYS_VEHICLE - #define DEBUG_ENABLED_sys_vehicle_damage - #define DEBUG_ENABLED_SYS_WEAPONREST - #define DEBUG_ENABLED_SYS_WOUNDS + #define DEBUG_ENABLED_ADDONS + #define DEBUG_ENABLED_ATTACHMENTS + #define DEBUG_ENABLED_weapons_backblast + #define DEBUG_ENABLED_BLOOD + #define DEBUG_ENABLED_CARTRIDGES + #define DEBUG_ENABLED_CRATERS + #define DEBUG_ENABLED_CREWPROTECTION + #define DEBUG_ENABLED_DUMMIES + #define DEBUG_ENABLED_EJECT + #define DEBUG_ENABLED_EXPLOSIVES + #define DEBUG_ENABLED_FLARES + #define DEBUG_ENABLED_FLASHBANG + #define DEBUG_ENABLED_GRENADETHROW + #define DEBUG_ENABLED_HUNTIR + #define DEBUG_ENABLED_INTERACTION + #define DEBUG_ENABLED_IRSTROBE + #define DEBUG_ENABLED_MULTI_BARREL + #define DEBUG_ENABLED_MUZZLEBLAST + #define DEBUG_ENABLED_NVG + #define DEBUG_ENABLED_weapons_overheating + #define DEBUG_ENABLED_RECOILDUST + #define DEBUG_ENABLED_ROCKET_BALLISTICS + #define DEBUG_ENABLED_SANDBAG + #define DEBUG_ENABLED_SHOTGUN + #define DEBUG_ENABLED_SIGHT_ADJUSTMENT_AT + #define DEBUG_ENABLED_SIGHT_ADJUSTMENT_GL + #define DEBUG_ENABLED_SIGHT_ADJUSTMENT_RIFLE + #define DEBUG_ENABLED_SMAW_SPOTTINGRIFLE + #define DEBUG_ENABLED_TRACERS + #define DEBUG_ENABLED_TRACKING + #define DEBUG_ENABLED_VIEWBLOCK + #define DEBUG_ENABLED_VEHICLE + #define DEBUG_ENABLED_vehicle_damage + #define DEBUG_ENABLED_WEAPONREST + #define DEBUG_ENABLED_WOUNDS */ diff --git a/addons/missileguidance/$PBOPREFIX$ b/addons/missileguidance/$PBOPREFIX$ new file mode 100644 index 0000000000..a2a17e3615 --- /dev/null +++ b/addons/missileguidance/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\Addons\missileguidance \ No newline at end of file diff --git a/addons/missileguidance/CfgAmmo.hpp b/addons/missileguidance/CfgAmmo.hpp new file mode 100644 index 0000000000..1fdd580724 --- /dev/null +++ b/addons/missileguidance/CfgAmmo.hpp @@ -0,0 +1,10 @@ +class CfgAmmo { + class MissileBase; + + class M_PG_AT : MissileBase { + irLock = 0; + laserLock = 0; + airLock = 0; + manualControl = 0; + }; +}; \ No newline at end of file diff --git a/addons/missileguidance/CfgEventhandlers.hpp b/addons/missileguidance/CfgEventhandlers.hpp new file mode 100644 index 0000000000..faa5edef0b --- /dev/null +++ b/addons/missileguidance/CfgEventhandlers.hpp @@ -0,0 +1,17 @@ +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_pre_init)); + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_post_init)); + }; +}; + +class Extended_FiredBIS_EventHandlers { + class AllVehicles { + ADDON = QUOTE(_this call FUNC(fired)); + }; +}; \ No newline at end of file diff --git a/addons/missileguidance/CfgWeapons.hpp b/addons/missileguidance/CfgWeapons.hpp new file mode 100644 index 0000000000..33c2bfe8de --- /dev/null +++ b/addons/missileguidance/CfgWeapons.hpp @@ -0,0 +1,34 @@ +class CfgWeapons { + class CannonCore; + class LauncherCore; + class Mode_SemiAuto; + + class RocketPods: LauncherCore { + canLock = 1; + }; + class missiles_DAGR: RocketPods { + canLock = 1; + }; + /* + class autocannon_Base_F: CannonCore { + canLock = 1; + }; + class cannon_120mm: CannonCore { + canLock = 1; + + class player : Mode_SemiAuto { + canLock = 1; + }; + }; + class gatling_25mm: CannonCore { + canLock = 1; + }; + class autocannon_35mm: CannonCore { + canLock = 1; + }; + + class launch_NLAW_F: Launcher_Base_F + { + canLock = 1; + };*/ +}; \ No newline at end of file diff --git a/addons/missileguidance/XEH_post_init.sqf b/addons/missileguidance/XEH_post_init.sqf new file mode 100644 index 0000000000..6904ee6c47 --- /dev/null +++ b/addons/missileguidance/XEH_post_init.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" +NO_DEDICATED; + diff --git a/addons/missileguidance/XEH_pre_init.sqf b/addons/missileguidance/XEH_pre_init.sqf new file mode 100644 index 0000000000..8aa557f838 --- /dev/null +++ b/addons/missileguidance/XEH_pre_init.sqf @@ -0,0 +1,14 @@ +#include "script_component.hpp" + +PREP(rotateVectLineGetMap); +PREP(rotateVectLine); + +PREP(translateToModelSpace); +PREP(translateToWeaponSpace); + +PREP(fired); + +PREP(guidance_DAGR); +PREP(guidance_LGB); +PREP(guidance_HellfireII); +FUNC(getPosASL) = {visiblePositionASL (_this select 0)}; \ No newline at end of file diff --git a/addons/missileguidance/config.cpp b/addons/missileguidance/config.cpp new file mode 100644 index 0000000000..42d23c98c0 --- /dev/null +++ b/addons/missileguidance/config.cpp @@ -0,0 +1,15 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { "uo_main", "ace__laser", "a3_ui_f" }; + version = VERSION; + }; +}; + +#include "CfgEventhandlers.hpp" +#include "CfgAmmo.hpp" +#include "CfgWeapons.hpp" \ No newline at end of file diff --git a/addons/missileguidance/fnc_fired.sqf b/addons/missileguidance/fnc_fired.sqf new file mode 100644 index 0000000000..dd0cba4fb8 --- /dev/null +++ b/addons/missileguidance/fnc_fired.sqf @@ -0,0 +1,11 @@ +//#define DEBUG_MODE_FULL +#include "script_component.hpp" +//_this=[TEST_AI_HELICOPTER,"missiles_DAGR","missiles_DAGR","Far_AI","M_PG_AT","24Rnd_PG_missiles",163988: rocket_01_fly_f.p3d] +TRACE_1("enter", _this); +PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + +if(!local _shooter) exitWith { false }; +if(_weapon == "missiles_DAGR") then { + //_this call FUNC(guidance_DAGR); + _this call FUNC(guidance_HellfireII); +}; \ No newline at end of file diff --git a/addons/missileguidance/fnc_guidance_DAGR.sqf b/addons/missileguidance/fnc_guidance_DAGR.sqf new file mode 100644 index 0000000000..4461c1223f --- /dev/null +++ b/addons/missileguidance/fnc_guidance_DAGR.sqf @@ -0,0 +1,113 @@ +//#define DEBUG_MODE_FULL +#include "script_component.hpp" + +FUNC(guidance_DIRECT_LOAL_PFH) = { + //TRACE_1("enter", _this); + _args = _this select 0; + //PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + _shooter = _args select 0; + _dagr = _args select 6; + _curVelocity = velocity _dagr; + + if(!alive _dagr || isNull _dagr || isNull _shooter) exitWith { + [(_this select 1)] call cba_fnc_removePerFrameHandler; + }; + + _targets = [_dagr, ACE_DEFAULT_LASER_CODE, 70, _curVelocity] call ace_laser_fnc_findLaserDesignator; + TRACE_2("Targets", _target, _targets); + + if((_targets select 0)) then { + _target = _targets select 1; + + // player sideChat "FUCK!"; + // drop ["\a3\data_f\Cl_basic","","Billboard",1,20,(getPos _dagr),[0,0,0],1,1.275,1.0,0.0,[5],[[1,0,0,1]],[0],0.0,2.0,"","",""]; + + + _yVec = vectorDir _dagr; + _zVec = vectorUp _dagr; + _xVec = vectorNormalized (_yVec vectorCrossProduct _zVec); + + _dagrPos = getPosASL _dagr; + // player sideChat "G!"; + _targetPos = getPosASL _target; + if((count _targetPos) > 0) then { + _distanceToTarget = _dagrPos vectorDistance _targetPos; + + _addHeight = [0,0,(_dagrPos distance _targetPos)*0.02]; + #ifdef DEBUG_MODE_FULL + drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]]; + #endif + + _targetPos = _targetPos vectorAdd _addHeight; + + _def = 0.0050; + + _targetVectorSeeker = [_dagr, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace); + // _targetVectorSeeker = _dagr worldToModel (ASLtoATL _targetPos); + // _targetVectorSeeker = [0,0,0] vectorFromTo _targetVectorSeeker; + _yaw = 0.0; + if((_targetVectorSeeker select 0) < 0) then { + _yaw = -_def; + } else { + if((_targetVectorSeeker select 0) > 0) then { + _yaw = _def; + }; + }; + + _pitch = 0.0; + if((_targetVectorSeeker select 2) < 0) then { + _pitch = -_def; + } else { + if((_targetVectorSeeker select 2) > 0) then { + _pitch = _def; + }; + }; + #ifdef DEBUG_MODE_FULL + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _dagrPos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"]; + drawLine3D [ASLtoATL _dagrPos, ASLtoATL _targetPos, [1,0,0,1]]; + + _distance = ([getPos startPos, _dagrPos] call BIS_fnc_distance2D); + _marker = createMarkerLocal [format["m%1", MARKERCOUNT], [_distance, _dagrPos select 2]]; + _marker setMarkerTypeLocal "mil_dot"; + _marker setMarkerColorLocal "ColorRed"; + + MARKERCOUNT = MARKERCOUNT + 1; + #endif + + if(accTime > 0) then { + _outVector = [_dagr, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace); + // _outVector = _dagr modelToWorld [_yaw, 1, _pitch]; + // _outVector = ATLtoASL _outVector; + _vectorTo = _dagrPos vectorFromTo _outVector; + + // hintSilent format["v: %1", _vectorTo]; + + // _dagr setVectorDir _vectorTo; + _dagr setVectorDirAndUp [_vectorTo, vectorUp _dagr]; + }; + + #ifdef DEBUG_MODE_FULL + hintSilent format["d: %1", _distanceToTarget]; + #endif + }; + }; +}; + +FUNC(guidance_DAGR_DIRECT_LOAL) = { + PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + + GVAR(lastTime) = time; + [FUNC(guidance_DIRECT_LOAL_PFH), 0, _this] call cba_fnc_addPerFrameHandler; +}; + +PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); +_fireMode = _shooter getVariable ["ACE_FIRE_SELECTION", ACE_DEFAULT_FIRE_SELECTION]; + +switch (_fireMode select 0) do { + // Default to FIREMODE_DIRECT_LOAL + // FIREMODE_DIRECT_LOAL + default { + LOG("Initiating DAGR FIREMODE_DIRECT_LOAL"); + _this call FUNC(guidance_DAGR_DIRECT_LOAL); + }; +}; \ No newline at end of file diff --git a/addons/missileguidance/fnc_guidance_HellfireII.sqf b/addons/missileguidance/fnc_guidance_HellfireII.sqf new file mode 100644 index 0000000000..d7d56b7d88 --- /dev/null +++ b/addons/missileguidance/fnc_guidance_HellfireII.sqf @@ -0,0 +1,249 @@ +#define DEBUG_MODE_FULL +#include "script_component.hpp" + +FUNC(guidance_Hellfire_LOAL_HI_PFH) = { + //TRACE_1("enter", _this); + _args = _this select 0; + //PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + _shooter = _args select 0; + _missile = _args select 6; + _curVelocity = velocity _missile; + + if(!alive _missile || isNull _missile || isNull _shooter) exitWith { + [(_this select 1)] call cba_fnc_removePerFrameHandler; + }; + + _launchPos = _shooter getVariable [QGVAR(launchPos), nil]; + if(isNil "_launchPos") then { + TRACE_1("Setting launch parameters", ""); + _launchPos = getPosASL _shooter; + _shooter setVariable [QGVAR(launchPos), _launchPos, false]; + _shooter setVariable [QGVAR(launchTime), diag_tickTime, false]; + }; + + _targets = [_missile, ACE_DEFAULT_LASER_CODE, 70, _curVelocity] call ace__laser_fnc_findLaserDesignator; + _addHeight = [0,0,0]; + if((_targets select 0)) then { + _target = _targets select 1; + TRACE_2("Targets", _target, _targets); + + _yVec = vectorDir _missile; + _zVec = vectorUp _missile; + _xVec = vectorNormalized (_yVec vectorCrossProduct _zVec); + + _missilePos = getPosASL _missile; + // player sideChat "G!"; + _targetPos = getPosASL _target; + TRACE_4("Phase Check", _launchPos, _missilePos, _targetPos, (_missilePos distance _targetPos)); + if((count _targetPos) > 0) then { + _distanceToTarget = _missilePos vectorDistance _targetPos; + + _defPitch = 0.05; + + if((_launchPos distance _missilePos) < 400 && (_targetPos distance _missilePos) > 400) then { + _addHeight = [0,0,(_targetPos select 2) + ((_launchPos distance _targetPos)*2)]; + TRACE_1("Climb phase", _addHeight); + //_defPitch = 0.1; + } else { + // Covered half the distance, go terminal + if((_missilePos distance _targetPos) < (_launchPos distance _targetPos) / 2) then { + TRACE_1("TERMINAL", ""); + } else { + if((_missilePos select 2) > (_targetPos select 2)) then { + _heightDiff = (_missilePos select 2) - (_targetPos select 2); + TRACE_1("Coasting", _heightDiff); + _addHeight = [0,0, _heightDiff]; + }; + }; + }; + _targetPos = _targetPos vectorAdd _addHeight; + + _defYaw = 0.0035; + + + _targetVectorSeeker = [_missile, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace); + _yaw = 0.0; + if((_targetVectorSeeker select 0) < 0) then { + _yaw = -_defYaw; + } else { + if((_targetVectorSeeker select 0) > 0) then { + _yaw = _defYaw; + }; + }; + + _pitch = 0.0; + if((_targetVectorSeeker select 2) < 0) then { + _pitch = -_defPitch; + } else { + if((_targetVectorSeeker select 2) > 0) then { + _pitch = _defPitch; + }; + }; + #ifdef DEBUG_MODE_FULL + drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]]; + + _light = "#lightpoint" createVehicleLocal (getPos _missile); + _light setLightBrightness 1.0; + _light setLightAmbient [1.0, 0.0, 0.0]; + _light setLightColor [1.0, 0.0, 0.0]; + + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _missilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"]; + drawLine3D [ASLtoATL _missilePos, ASLtoATL _targetPos, [1,0,0,1]]; + + _distance = ([getPos startPos, _missilePos] call BIS_fnc_distance2D); + _marker = createMarkerLocal [format["m%1", MARKERCOUNT], [_distance, _missilePos select 2]]; + _marker setMarkerTypeLocal "mil_dot"; + _marker setMarkerColorLocal "ColorRed"; + + MARKERCOUNT = MARKERCOUNT + 1; + #endif + + if(accTime > 0) then { + _outVector = [_missile, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace); + + _vectorTo = _missilePos vectorFromTo _outVector; + _missile setVectorDirAndUp [_vectorTo, vectorUp _missile]; + }; + + #ifdef DEBUG_MODE_FULL + hintSilent format["d: %1", _distanceToTarget]; + #endif + }; + }; +}; + +FUNC(guidance_Hellfire_LOAL_DIR_PFH) = { + //TRACE_1("enter", _this); + _args = _this select 0; + //PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + _shooter = _args select 0; + _missile = _args select 6; + _curVelocity = velocity _missile; + + if(!alive _missile || isNull _missile || isNull _shooter) exitWith { + [(_this select 1)] call cba_fnc_removePerFrameHandler; + }; + + _launchPos = _shooter getVariable [QGVAR(launchPos), nil]; + if(isNil "_launchPos") then { + TRACE_1("Setting launch parameters", ""); + _launchPos = getPosASL _shooter; + _shooter setVariable [QGVAR(launchPos), _launchPos, false]; + _shooter setVariable [QGVAR(launchTime), diag_tickTime, false]; + }; + + _targets = [_missile, ACE_DEFAULT_LASER_CODE, 70, _curVelocity] call ace__laser_fnc_findLaserDesignator; + _addHeight = [0,0,0]; + if((_targets select 0)) then { + _target = _targets select 1; + TRACE_2("Targets", _target, _targets); + + _yVec = vectorDir _missile; + _zVec = vectorUp _missile; + _xVec = vectorNormalized (_yVec vectorCrossProduct _zVec); + + _missilePos = getPosASL _missile; + // player sideChat "G!"; + _targetPos = getPosASL _target; + TRACE_4("Phase Check", _launchPos, _missilePos, _targetPos, (_missilePos distance _targetPos)); + if((count _targetPos) > 0) then { + _distanceToTarget = _missilePos vectorDistance _targetPos; + + if((_launchPos distance _missilePos) < 400 && (_targetPos distance _missilePos) > 400) then { + _addHeight = [0,0,(_targetPos select 2) + (_missilePos distance _targetPos)*0.5]; + TRACE_1("Climb phase", _addHeight); + } else { + // Covered half the distance, go terminal + if((_missilePos distance _targetPos) < (_launchPos distance _targetPos) / 2) then { + TRACE_1("TERMINAL", ""); + } else { + if((_missilePos select 2) > (_targetPos select 2)) then { + _heightDiff = (_missilePos select 2) - (_targetPos select 2); + TRACE_1("Coasting", _heightDiff); + _addHeight = [0,0, _heightDiff]; + }; + }; + }; + _targetPos = _targetPos vectorAdd _addHeight; + + _defYaw = 0.0035; + _defPitch = 0.0075; + + _targetVectorSeeker = [_missile, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace); + _yaw = 0.0; + if((_targetVectorSeeker select 0) < 0) then { + _yaw = -_defYaw; + } else { + if((_targetVectorSeeker select 0) > 0) then { + _yaw = _defYaw; + }; + }; + + _pitch = 0.0; + if((_targetVectorSeeker select 2) < 0) then { + _pitch = -_defPitch; + } else { + if((_targetVectorSeeker select 2) > 0) then { + _pitch = _defPitch; + }; + }; + #ifdef DEBUG_MODE_FULL + drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]]; + + _light = "#lightpoint" createVehicleLocal (getPos _missile); + _light setLightBrightness 1.0; + _light setLightAmbient [1.0, 0.0, 0.0]; + _light setLightColor [1.0, 0.0, 0.0]; + + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _missilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"]; + drawLine3D [ASLtoATL _missilePos, ASLtoATL _targetPos, [1,0,0,1]]; + + _distance = ([getPos startPos, _missilePos] call BIS_fnc_distance2D); + _marker = createMarkerLocal [format["m%1", MARKERCOUNT], [_distance, _missilePos select 2]]; + _marker setMarkerTypeLocal "mil_dot"; + _marker setMarkerColorLocal "ColorRed"; + + MARKERCOUNT = MARKERCOUNT + 1; + #endif + + if(accTime > 0) then { + _outVector = [_missile, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace); + + _vectorTo = _missilePos vectorFromTo _outVector; + _missile setVectorDirAndUp [_vectorTo, vectorUp _missile]; + }; + + #ifdef DEBUG_MODE_FULL + hintSilent format["d: %1", _distanceToTarget]; + #endif + }; + }; +}; + + +FUNC(guidance_Hellfire_LOAL_HI) = { + PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + + GVAR(lastTime) = time; + [FUNC(guidance_Hellfire_LOAL_HI_PFH), 0, _this] call cba_fnc_addPerFrameHandler; +}; + + +FUNC(guidance_Hellfire_LOAL_DIR) = { + PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + + GVAR(lastTime) = time; + [FUNC(guidance_Hellfire_LOAL_DIR_PFH), 0, _this] call cba_fnc_addPerFrameHandler; +}; + +PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); +_fireMode = _shooter getVariable ["ACE_FIRE_SELECTION", ACE_DEFAULT_FIRE_SELECTION]; + +switch (_fireMode select 0) do { + // Default to FIREMODE_DIRECT_LOAL + // FIREMODE_DIRECT_LOAL + default { + LOG("Initiating Hellfire II FIREMODE_LOAL_DIR"); + _this call FUNC(guidance_Hellfire_LOAL_HI); + }; +}; \ No newline at end of file diff --git a/addons/missileguidance/fnc_guidance_LGB.sqf b/addons/missileguidance/fnc_guidance_LGB.sqf new file mode 100644 index 0000000000..e9e8754f19 --- /dev/null +++ b/addons/missileguidance/fnc_guidance_LGB.sqf @@ -0,0 +1,109 @@ +#define DEBUG_MODE_FULL +#include "script_component.hpp" + +FUNC(guidance_LGB_LOAL_PFH) = { + //TRACE_1("enter", _this); + _args = _this select 0; + //PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + _lgb = _args select 6; + _curVelocity = velocity _lgb; + + if(!alive _lgb) exitWith { + [(_this select 1)] call cba_fnc_removePerFrameHandler; + }; + + _targets = [_lgb, ACE_DEFAULT_LASER_CODE, 70, _curVelocity] call uo_laser_fnc_findLaserDesignator; + //TRACE_2("Targets", _target, _targets); + + if((_targets select 0)) then { + _target = _targets select 1; + + // player sideChat "FUCK!"; + // drop ["\a3\data_f\Cl_basic","","Billboard",1,20,(getPos _lgb),[0,0,0],1,1.275,1.0,0.0,[5],[[1,0,0,1]],[0],0.0,2.0,"","",""]; + + + _yVec = vectorDir _lgb; + _zVec = vectorUp _lgb; + _xVec = vectorNormalized (_yVec vectorCrossProduct _zVec); + + _lgbPos = getPosASL _lgb; + // player sideChat "G!"; + _targetPos = getPosASL _target; + if((count _targetPos) > 0) then { + // player sideChat format["f: %1", _targetPos]; + _addHeight = [0,0,(_lgbPos distance _targetPos)*0.06]; + // drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]]; + _targetPos = _targetPos vectorAdd _addHeight; + + + + _def = 0.0025; + + _targetVectorSeeker = [_lgb, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace); + // _targetVectorSeeker = _lgb worldToModel (ASLtoATL _targetPos); + // _targetVectorSeeker = [0,0,0] vectorFromTo _targetVectorSeeker; + _yaw = 0.0; + if((_targetVectorSeeker select 0) < 0) then { + _yaw = -_def; + } else { + if((_targetVectorSeeker select 0) > 0) then { + _yaw = _def; + }; + }; + + _pitch = 0.0; + if((_targetVectorSeeker select 2) < 0) then { + _pitch = -_def; + } else { + if((_targetVectorSeeker select 2) > 0) then { + _pitch = _def; + }; + }; + #ifdef DEBUG_MODE_FULL + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _lgbPos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"]; + drawLine3D [ASLtoATL _lgbPos, ASLtoATL _targetPos, [1,0,0,1]]; + + _distance = ([getPos startPos, _lgbPos] call BIS_fnc_distance2D); + _marker = createMarkerLocal [format["m%1", MARKERCOUNT], [_distance, _lgbPos select 2]]; + _marker setMarkerTypeLocal "mil_dot"; + _marker setMarkerColorLocal "ColorRed"; + + MARKERCOUNT = MARKERCOUNT + 1; + #endif + + if(accTime > 0) then { + _outVector = [_lgb, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace); + // _outVector = _lgb modelToWorld [_yaw, 1, _pitch]; + // _outVector = ATLtoASL _outVector; + _vectorTo = _lgbPos vectorFromTo _outVector; + + // hintSilent format["v: %1", _vectorTo]; + + // _lgb setVectorDir _vectorTo; + _lgb setVectorDirAndUp [_vectorTo, vectorUp _lgb]; + }; + + #ifdef DEBUG_MODE_FULL + hintSilent format["d: %1", _lgbPos vectorDistance _targetPos]; + #endif + }; + }; +}; + +FUNC(guidance_LGB_LOAL) = { + PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + + [FUNC(guidance_LGB_LOAL_PFH), 0, _this] call cba_fnc_addPerFrameHandler; +}; + +PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); +_fireMode = _shooter getVariable ["ACE_FIRE_SELECTION", ACE_DEFAULT_FIRE_SELECTION]; + +switch (_fireMode select 0) do { + // Default to FIREMODE_DIRECT_LOAL + // FIREMODE_DIRECT_LOAL + default { + LOG("Initiating FIREMODE_DIRECT_LOAL"); + _this call FUNC(guidance_LGB_LOAL); + }; +}; \ No newline at end of file diff --git a/addons/missileguidance/fnc_rotateVectLine.sqf b/addons/missileguidance/fnc_rotateVectLine.sqf new file mode 100644 index 0000000000..b0360cc330 --- /dev/null +++ b/addons/missileguidance/fnc_rotateVectLine.sqf @@ -0,0 +1,38 @@ +#include "script_component.hpp" + +_map = _this select 0; +_theta = _this select 1; + +_p = _map select 0; +_p1 = _map select 1; +_p2 = _map select 2; + +_q1 = +(_map select 3); +_q2 = +(_map select 4); +_u = _map select 5; +_d = _map select 6; + +/* Step 4 */ +_q2 set[0, (_q1 select 0) * cos(_theta) - (_q1 select 1) * sin(_theta)]; +_q2 set[1, (_q1 select 0) * sin(_theta) + (_q1 select 1) * cos(_theta)]; +_q2 set[2, (_q1 select 2)]; + +/* Inverse of step 3 */ +_q1 set[0, (_q2 select 0) * _d + (_q2 select 2) * (_u select 0)]; +_q1 set[1, (_q2 select 1)]; +_q1 set[2, - (_q2 select 0) * (_u select 0) + (_q2 select 2) * _d]; + +/* Inverse of step 2 */ +if (_d != 0) then { + _q2 set[0, (_q1 select 0)]; + _q2 set[1, (_q1 select 1) * (_u select 2) / _d + (_q1 select 2) * (_u select 1) / _d]; + _q2 set[2, - (_q1 select 1) * (_u select 1) / _d + (_q1 select 2) * (_u select 2) / _d]; +} else { + _q2 = _q1; +}; + +/* Inverse of step 1 */ +_q1 set[0, (_q2 select 0) + (_p1 select 0)]; +_q1 set[1, (_q2 select 1) + (_p1 select 1)]; +_q1 set[2, (_q2 select 2) + (_p1 select 2)]; +_q1; \ No newline at end of file diff --git a/addons/missileguidance/fnc_rotateVectLineGetMap.sqf b/addons/missileguidance/fnc_rotateVectLineGetMap.sqf new file mode 100644 index 0000000000..fdbd6533ef --- /dev/null +++ b/addons/missileguidance/fnc_rotateVectLineGetMap.sqf @@ -0,0 +1,37 @@ +#include "script_component.hpp" + +private ["_p", "_theta", "_p1", "_p2", "_q1", "_q2", "_u", "_d"]; +_p = _this select 0; +_p1 = _this select 1; +_p2 = _this select 2; + +_q1 = []; +_q2 = []; +_u = []; + +/* Step 1 */ +_q1 set[0, (_p select 0) - (_p1 select 0)]; +_q1 set[1, (_p select 1) - (_p1 select 1)]; +_q1 set[2, (_p select 2) - (_p1 select 2)]; + +_u set[0, (_p2 select 0) - (_p1 select 0)]; +_u set[1, (_p2 select 1) - (_p1 select 1)]; +_u set[2, (_p2 select 2) - (_p1 select 2)]; +_u = _u call BIS_fnc_unitVector; +_d = sqrt((_u select 1)*(_u select 1) + (_u select 2)*(_u select 2)); + +/* Step 2 */ +if (_d != 0) then { + _q2 set[0, (_q1 select 0)]; + _q2 set[1, (_q1 select 1) * (_u select 2) / _d - (_q1 select 2) * (_u select 1) / _d]; + _q2 set[2, (_q1 select 1) * (_u select 1) / _d + (_q1 select 2) * (_u select 2) / _d]; +} else { + _q2 = _q1; +}; + +/* Step 3 */ +_q1 set[0, (_q2 select 0) * _d - (_q2 select 2) * (_u select 0)]; +_q1 set[1, (_q2 select 1)]; +_q1 set[2, (_q2 select 0) * (_u select 0) + (_q2 select 2) * _d]; + +[_p, _p1, _p2, _q1, _q2, _u, _d] \ No newline at end of file diff --git a/addons/missileguidance/fnc_translateToModelSpace.sqf b/addons/missileguidance/fnc_translateToModelSpace.sqf new file mode 100644 index 0000000000..1e2e930ac7 --- /dev/null +++ b/addons/missileguidance/fnc_translateToModelSpace.sqf @@ -0,0 +1,16 @@ +_object = _this select 0; +_origin = getPosASL _object; +_matrix = _this select 1; +_xVec = _matrix select 0; +_yVec = _matrix select 1; +_zVec = _matrix select 2; + +_offset = _this select 2; + +_x = _offset select 0; +_y = _offset select 1; +_z = _offset select 2; + +_out = (((_xVec vectorMultiply _x) vectorAdd (_yVec vectorMultiply _y)) vectorAdd (_zVec vectorMultiply _z)) vectorAdd _origin; + +_out; \ No newline at end of file diff --git a/addons/missileguidance/fnc_translateToWeaponSpace.sqf b/addons/missileguidance/fnc_translateToWeaponSpace.sqf new file mode 100644 index 0000000000..406d81b145 --- /dev/null +++ b/addons/missileguidance/fnc_translateToWeaponSpace.sqf @@ -0,0 +1,22 @@ +_object = _this select 0; +_origin = getPosASL _object; +_matrix = _this select 1; +_xVec = _matrix select 0; +_yVec = _matrix select 1; +_zVec = _matrix select 2; + +_offset = _this select 2; + +_offset = _offset vectorDiff _origin; + +_x = _offset select 0; +_y = _offset select 1; +_z = _offset select 2; + +_out = [ + ((_xVec select 0)*_x) + ((_xVec select 1)*_y) + ((_xVec select 2)*_z), + ((_yVec select 0)*_x) + ((_yVec select 1)*_y) + ((_yVec select 2)*_z), + ((_zVec select 0)*_x) + ((_zVec select 1)*_y) + ((_zVec select 2)*_z) + ]; + +_out; \ No newline at end of file diff --git a/addons/missileguidance/script_component.hpp b/addons/missileguidance/script_component.hpp new file mode 100644 index 0000000000..886764be2b --- /dev/null +++ b/addons/missileguidance/script_component.hpp @@ -0,0 +1,14 @@ +#define COMPONENT missileguidance +#include "\z\ace\Addons\main\script_mod.hpp" + +#ifdef DEBUG_ENABLED_MISSILEGUIDANCE + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_MISSILEGUIDANCE + #define DEBUG_SETTINGS DEBUG_SETTINGS_MISSILEGUIDANCE +#endif + +#include "\z\ace\Addons\main\script_macros.hpp" + +#define FIREMODE_DIRECT_LOAL 1 \ No newline at end of file diff --git a/addons/wep_dragon/$PBOPREFIX$ b/addons/wep_dragon/$PBOPREFIX$ new file mode 100644 index 0000000000..11c855b566 --- /dev/null +++ b/addons/wep_dragon/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\Addons\wep_dragon \ No newline at end of file diff --git a/addons/wep_dragon/CfgAmmo.hpp b/addons/wep_dragon/CfgAmmo.hpp new file mode 100644 index 0000000000..e51ea122b9 --- /dev/null +++ b/addons/wep_dragon/CfgAmmo.hpp @@ -0,0 +1,77 @@ +class CfgAmmo { + class MissileBase; + class ShellBase; + + class ace_m47_dragon_serviceCharge : ShellBase { + hit = 1; + indirectHit = 2; + indirectHitRange = 1; + typicalSpeed = 100; + explosive = 1; + cost = 300; + model = "\ca\weapons\empty"; + airFriction = 0; + timeToLive = 1; + explosionTime = 0.001; + soundFly[] = {"",1,1}; + soundEngine[] = {"",1,4}; + CraterEffects = ""; + explosionEffects = "ace_m47_serviceExplosion"; + hitarmor[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitbuilding[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitconcrete[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitdefault[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitfoliage[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitglass[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitglassarmored[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitgroundhard[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitgroundsoft[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitiron[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitman[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitmetal[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitmetalplate[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitplastic[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitrubber[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + hitwood[] = {"soundDefault1", 0.33, "soundDefault2", 0.33, "soundDefault3", 0.33}; + sounddefault1[] = {"\x\ace\addons\arty_ammunition\Sounds\base_eject", 56.2341, 1, 1800}; + sounddefault2[] = {"\x\ace\addons\arty_ammunition\Sounds\base_eject", 56.2341, 1, 1800}; + sounddefault3[] = {"\x\ace\addons\arty_ammunition\Sounds\base_eject", 56.2341, 1, 1800}; + soundHit[] = {"\x\ace\addons\arty_ammunition\Sounds\base_eject",56.23413,1,1800}; + }; + + class M_47_AT_EP1: MissileBase { + ace_towsmoke = 0; // no trail + six_tracerenable = 0; // can't find it? + ace_guidance_type = "dragon"; + soundFly[] = {"",0,1,0}; + soundEngine[] = {"",0,1,0}; + }; + + class ace_missile_dragon : M_47_AT_EP1 { + model = PATHTOF(models\dragon.p3d); + maxSpeed = 120; + thrust = 0; + initTime = 0; + thrustTime = 0; + sideAirFriction = 0.025; + explosionEffects = ""; + CraterEffects = ""; + hitarmor[] = {"soundhit", 1}; + hitbuilding[] = {"soundhit", 1}; + hitconcrete[] = {"soundhit", 1}; + hitdefault[] = {"soundhit", 1}; + hitfoliage[] = {"soundhit", 1}; + hitglass[] = {"soundhit", 1}; + hitglassarmored[] = {"soundhit", 1}; + hitgroundhard[] = {"soundhit", 1}; + hitgroundsoft[] = {"soundhit", 1}; + hitiron[] = {"soundhit", 1}; + hitman[] = {"soundhit", 1}; + hitmetal[] = {"soundhit", 1}; + hitmetalplate[] = {"soundhit", 1}; + hitplastic[] = {"soundhit", 1}; + hitrubber[] = {"soundhit", 1}; + hitwood[] = {"soundhit", 1}; + soundhit[] = {"", 0, 1}; + }; +}; \ No newline at end of file diff --git a/addons/wep_dragon/CfgEventhandlers.hpp b/addons/wep_dragon/CfgEventhandlers.hpp new file mode 100644 index 0000000000..d22d71eb89 --- /dev/null +++ b/addons/wep_dragon/CfgEventhandlers.hpp @@ -0,0 +1,11 @@ +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_pre_init)); + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_post_init)); + }; +}; \ No newline at end of file diff --git a/addons/wep_dragon/CfgMagazines.hpp b/addons/wep_dragon/CfgMagazines.hpp new file mode 100644 index 0000000000..904f53a0c9 --- /dev/null +++ b/addons/wep_dragon/CfgMagazines.hpp @@ -0,0 +1,7 @@ +class CfgMagazines { + class CA_LauncherMagazine; + + class Dragon_EP1: CA_LauncherMagazine { + model = PATHTOF(models\ace_m47_magazine.p3d); + }; +}; \ No newline at end of file diff --git a/addons/wep_dragon/CfgVehicles.hpp b/addons/wep_dragon/CfgVehicles.hpp new file mode 100644 index 0000000000..ec8e60a23f --- /dev/null +++ b/addons/wep_dragon/CfgVehicles.hpp @@ -0,0 +1,64 @@ +class CfgVehicles { + class LandVehicle; + + class StaticWeapon : LandVehicle { + class Turrets; + }; + + class StaticATWeapon : StaticWeapon { + class Turrets: Turrets { + class MainTurret; + }; + }; + + class ACE_M47_Static_Base : StaticATWeapon { + class Turrets: Turrets { + class MainTurret : MainTurret { + class ViewOptics; + }; + }; + } + + class ACE_M47_Static: ACE_M47_Static_Base { + scope = 1; // Hide it for now + model = PATHTOF(models\ace_m47_static.p3d); + displayName = "M47 Dragon"; + class Turrets: Turrets { + class MainTurret: MainTurret { + gunnerAction = "LowKORD_Gunner"; + GVAR(tracker) = "TOWLauncherSingle"; + gunnerOpticsModel = "\ca\Weapons_e\optics_m47"; + weapons[] = {"ACE_M47StaticLauncher"}; + magazines[] = {}; + class ViewOptics : ViewOptics { + initFov = DRAGON_FOV; + minFov = DRAGON_FOV; + maxFov = DRAGON_FOV; + }; + }; + }; + class AnimationSources { + class rest_rotate { + source="user"; + animPeriod=0.00001; + initPhase=-0.35; + maxValue="3.60"; + minValue="-3.60"; + }; + class optic_hide { + source="user"; + animPeriod=0.0001; + initPhase=1; + maxValue="1"; + minValue="0"; + }; + class missile_hide { + source="user"; + animPeriod=0.0001; + initPhase=0; + maxValue="1"; + minValue="0"; + }; + }; + }; +}; \ No newline at end of file diff --git a/addons/wep_dragon/CfgWeapons.hpp b/addons/wep_dragon/CfgWeapons.hpp new file mode 100644 index 0000000000..851796b260 --- /dev/null +++ b/addons/wep_dragon/CfgWeapons.hpp @@ -0,0 +1,45 @@ +class CfgWeapons { + class Weapon_Bag_Base; + class B_AT_01_weapon_F: Weapon_Bag_Base { + }; + class ACE_M47StaticLauncher: B_AT_01_weapon_F { + displayName = "M47 Dragon"; + canLock = 0; + handAnim[] = {"OFP2_ManSkeleton","\Ca\weapons_E\Data\Anim\M47.rtm"}; + sound[] = {"Ca\Sounds_E\Weapons_E\M47\M47_1",3.1622777,1,1200}; + drySound[] = {"Ca\Sounds_E\Weapons_E\M47\dry",0.0001,1,10}; + reloadMagazineSound[] = {"Ca\Sounds_E\Weapons_E\M47\rocket_reload",1.0,1,30}; + soundFly[] = {"",3.1622777,1,500}; + initSpeed = 20; + magazines[] = {"Dragon_EP1"}; + reloadTime = 0; + magazineReloadTime = 0; + }; + + class Launcher; + class M47Launcher_EP1: Launcher { + displayName = "M47 Dragon"; + canlock = 0; + model = PATHTOF(models\ace_m47_magazine.p3d); + picture = PATHTOF(textures\m47_dragon_item_ca.paa); + }; + class ACE_M47_Daysight: M47Launcher_EP1 { + displayName = $STR_DN_ACE_DRAGONSUP36; // Stay next to tubes in gear dialogs + model = PATHTOF(models\ace_m47_optic.p3d); + picture = PATHTOF(textures\m47_daysight_item_ca.paa); + optics = 1; + weaponInfoType = "RscWeaponEmpty"; + modelOptics = "\ca\Weapons_e\optics_m47"; + reloadaction = ""; + showSwitchAction = 1; + useAsBinocular = 1; + uipicture = ""; + descriptionshort = "SU-36/P Daysight"; + ace_disposable = 0; + magazines[] = {}; + type = 4096; + opticsPPEffects[] = {"OpticsCHAbera1","OpticsBlur1"}; + opticsZoomMin = 0.015; + opticsZoomMax = 0.015; + }; +}; \ No newline at end of file diff --git a/addons/wep_dragon/XEH_post_init.sqf b/addons/wep_dragon/XEH_post_init.sqf new file mode 100644 index 0000000000..6904ee6c47 --- /dev/null +++ b/addons/wep_dragon/XEH_post_init.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" +NO_DEDICATED; + diff --git a/addons/wep_dragon/XEH_pre_init.sqf b/addons/wep_dragon/XEH_pre_init.sqf new file mode 100644 index 0000000000..dc30361926 --- /dev/null +++ b/addons/wep_dragon/XEH_pre_init.sqf @@ -0,0 +1,2 @@ +#include "script_component.hpp" + diff --git a/addons/wep_dragon/config.cpp b/addons/wep_dragon/config.cpp new file mode 100644 index 0000000000..775fd26357 --- /dev/null +++ b/addons/wep_dragon/config.cpp @@ -0,0 +1,17 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + units[] = { "ACE_M47_Static" }; + weapons[] = { "ACE_M47StaticLauncher", "M47Launcher_EP1", "ACE_M47_Daysight" }; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { "uo_main", "a3_data_f", "a3_static_f"}; + version = VERSION; + }; +}; + +#include "CfgEventhandlers.hpp" +#include "CfgVehicles.hpp" +#include "CfgWeapons.hpp" +#include "CfgAmmo.hpp" +#include "CfgMagazines.hpp" \ No newline at end of file diff --git a/addons/wep_dragon/fnc_dragon_fired.sqf b/addons/wep_dragon/fnc_dragon_fired.sqf new file mode 100644 index 0000000000..ff97232aea --- /dev/null +++ b/addons/wep_dragon/fnc_dragon_fired.sqf @@ -0,0 +1,135 @@ +//fnc_fired.sqf +#include "script_component.hpp" +#define DRAGON_VELOCITY 100 +#define SERVICE_INTERVAL 0.3 +#define DRAGON_SERVICE_COUNT 60 +#define DRAGON_TRIM 1 +#define TRACKINTERVAL 0.025 + +if ((_this select 0) == player || {(gunner (_this select 0)) == player}) then { + if ((typeOf (_this select 6)) == "M_47_AT_EP1") then { + _missile = (_this select 6); + _vel = velocity _missile; + _ppos = getPosASL _missile; + _missile setPosATL [_ppos select 0, _ppos select 1, 5000]; + _unitVec = _vel call ACE_fnc_unitVector; + _spawnPos = [(_ppos select 0) + (_unitVec select 0), (_ppos select 1) + (_unitVec select 1), (_ppos select 2) + (_unitVec select 2)]; + _shell = "ace_missile_dragon" createVehicle _spawnPos; + _this set[6, _shell]; + _shell setPosASL _spawnPos; + + _newVel = [_unitVec, DRAGON_VELOCITY*1.25] call ACE_fnc_vectorMultiply; + _shell setVelocity _newVel; + _shell setVectorDir _unitVec; + _gunner = _this select 0; + //setAccTime 0.2; + + [ + { + _unitVec = (velocity _shell) call ACE_fnc_unitVector; + _polar = _unitVec call CBA_fnc_vect2polar; + _spos = getPosATL _shell; + _ppos = getPosASL _shell; + _screenPos = if (_spos select 2 > _ppos select 2) then {worldToScreen _ppos} else {worldToScreen _spos}; + + if (count _screenPos > 0 && {alive _gunner}) then { + _x = (((_screenPos select 0) - 0.5) max -1) min 1; + _y = (((_screenPos select 1) - 0.45) max -1) min 1; + _m = ((_shell distance _gunner)*0.009); + + //player sideChat format["x: %1, y: %2 m: %3 di: %4 spd: %5", _x*_m, _y*_m*-1, _m, (_shell distance _gunner), (speed _shell)]; + + _yDeg = 2.1; + _xDeg = 1.6; + _difEl = _yDeg*(_y*_m); + _difEl = ((_difEl min _yDeg) max (_yDeg*-1)); + if(_difEl < 0) then { + _difEl = _difEl / 2; + }; + _dir = _xDeg*(_x*_m)*-1; + _dir = ((_dir min _xDeg) max (_xDeg*-1)); + _difDir = (_polar select 1) + _dir; + if (_difDir < 0) then {_difDir = _difDir + 360}; + if (_difDir > 360) then {_difDir = _difDir - 360}; + //drop ["\Ca\Data\Cl_basic","","Billboard",1,5,(getPos _shell),[0,0,0],1,1.275,1.0,0.0,[1],[[1,0,0,0.25]],[0],0.0,2.0,"","",""]; + _firedAdjust = false; + _shellVelocity = velocity _shell; + _speed = (3.6*sqrt((_shellVelocity select 0)^2 + (_shellVelocity select 1)^2 + (_shellVelocity select 2)^2))*0.278; + //hint format["speed: %1\ndistance: %2\ntime: %3", _speed, (_gunner distance _shell), diag_tickTime-_startTime]; + if (diag_tickTime >= _timerCorrect && {_chargeCount > 0}) then { + if ((abs _dir) >= _xDeg/2) then { + _firedAdjust = true; + _difDir = (_polar select 1) + (_dir*0.25); + if (_difDir < 0) then {_difDir = _difDir + 360}; + if (_difDir > 360) then {_difDir = _difDir - 360}; + //player sideChat "CORRECT!"; + _timerCorrect = diag_tickTime+(SERVICE_INTERVAL*2); + _newVel = [DRAGON_VELOCITY, (_difDir), (_polar select 2)+(_difEl*0.25)+DRAGON_TRIM] call CBA_fnc_polar2vect; + _shell setVelocity _newVel; + _shell setVectorDir (_newVel call ACE_fnc_unitVector); + "ace_m47_dragon_serviceCharge" createVehicle (getPos _shell); + _chargeCount = _chargeCount - 1; + }; + }; + + if (!_firedAdjust && {diag_tickTime >= _timer} && {_chargeCount > 0}) then { + _timer = diag_tickTime+SERVICE_INTERVAL; + + _newVel = [DRAGON_VELOCITY, _difDir, (_polar select 2)+(_difEl)+DRAGON_TRIM] call CBA_fnc_polar2vect; + //_newVel = [(velocity _shell), _newVel] call ACE_fnc_vectorAdd; + // if(_difEl > 0) then { + // drop ["\Ca\Data\Cl_basic","","Billboard",1,5,(getPos _shell),[0,0,0],1,1.275,1.0,0.0,[0.5],[[0,1,0,1]],[0],0.0,2.0,"","",""]; + // } else { + // drop ["\Ca\Data\Cl_basic","","Billboard",1,5,(getPos _shell),[0,0,0],1,1.275,1.0,0.0,[0.5],[[0,0,1,1]],[0],0.0,2.0,"","",""]; + // }; + _shell setVelocity _newVel; + _shell setVectorDir (_newVel call ACE_fnc_unitVector); + + // charge FX + _shellCharge = "ace_m47_dragon_serviceCharge" createVehicle _ppos; + _shellCharge setPosASL _ppos; + _chargeCount = _chargeCount - 1; + }; + }; + _missile setPosATL [_ppos select 0, _ppos select 1, 5000]; + _prevTime = diag_tickTime; + }, + [_shell,_gunner,_unitVec,_missile], + 0.0, // delay + { + //init + _shell = _this select 0; + _gunner = _this select 1; + _chargeCount = DRAGON_SERVICE_COUNT; + _timer = diag_tickTime+SERVICE_INTERVAL; + _timerCorrect = _timer; + _originalVec = _this select 2; + _originalPolar = _originalVec call CBA_fnc_vect2polar; + _targetPolar = +_originalPolar; + _startTime = diag_tickTime; + _lastX = 1000; + _lastY = 1000; + // Return original missile at explosion + _missile = _this select 3; + // start from beginning + _prevTime = diag_tickTime - TRACKINTERVAL; + }, + { + // exit + if !(isNull _missile) then { + _missile setVelocity _newVel; + _missile setVectorDir (_newVel call ACE_fnc_unitVector); + _missile setPosASL _ppos; + }; + }, + { + diag_tickTime - _prevTime > TRACKINTERVAL + }, + {!alive _shell}, + [ + "_shell", "_gunner", "_chargeCount", "_timer", "_originalVec", "_originalPolar", "_timerCorrect", "_startTime", "_lastX", "_lastY", + "_missile", "_ppos", "_newVel", "_prevTime" + ] + ] call cba_common_fnc_addPerFrameHandlerLogic; + }; +}; \ No newline at end of file diff --git a/addons/wep_dragon/license.txt b/addons/wep_dragon/license.txt new file mode 100644 index 0000000000..ff5ec3e450 --- /dev/null +++ b/addons/wep_dragon/license.txt @@ -0,0 +1,79 @@ +License (short) +=============== + +You are free: +- to Share to copy, distribute and transmit the work + +Under the following conditions: +- Attribution You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work). +- Noncommercial You may not use this work for commercial purposes. +- No Derivative Works You may not alter, transform, or build upon this work. + +With the understanding that: + +Waiver Any of the above conditions can be waived if you get permission from the copyright holder. + +Public Domain Where the work or any of its elements is in the public domain under applicable law, that status is in no way affected by the license. + +Other Rights In no way are any of the following rights affected by the license: + - Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations; + - The author's moral rights; + - Rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights. + +Notice For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page. + + +Full license text +================= + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. + +1. Definitions + +"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. +"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License. +"Distribute" means to make available to the public the original and copies of the Work through sale or other transfer of ownership. +"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. +"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. +"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. +"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. +"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. +"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. +2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: + +to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; and, +to Distribute and Publicly Perform the Work including as incorporated in Collections. +The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats, but otherwise you have no rights to make Adaptations. Subject to 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights set forth in Section 4(d). + +4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: + +You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested. +You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in connection with the exchange of copyrighted works. +If You Distribute, or Publicly Perform the Work or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work. The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Collection, at a minimum such credit will appear, if a credit for all contributing authors of Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. +For the avoidance of doubt: + +Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; +Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and, +Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b). +Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + +This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. +Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. +8. Miscellaneous + +Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. +If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. +No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. +This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. +The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. diff --git a/addons/wep_dragon/model.cfg b/addons/wep_dragon/model.cfg new file mode 100644 index 0000000000..6aeaf2e95e --- /dev/null +++ b/addons/wep_dragon/model.cfg @@ -0,0 +1,96 @@ +class CfgSkeletons { + class Default { + isDiscrete = 1; + skeletonInherit = ""; + skeletonBones[] = {}; + }; + + class ace_m47_static_skeleton: Default { + skeletonInherit = "Default"; + skeletonBones[] = { + "bipod","", + "grav_box","bipod", + "launcher","grav_box", + "optic","launcher", + "missile","launcher" + }; + }; +}; + +class CfgModels { + class Default { + sectionsInherit = ""; + sections[] = {}; + }; + + class ace_m47_static: Default { + sectionsInherit = "Default"; + sections[] = {}; + skeletonName = "ace_m47_static_skeleton"; + class Animations { + class MainGun { + type="rotation"; + selection="launcher"; + sourceAddress = "clamp"; + source="MainGun"; + axis="elevate_axis"; + animPeriod=0.01; + initPhase=0; + maxValue="rad 360"; + minValue="rad -360"; + angle1="rad 360"; + angle0="rad -360"; + }; + class MainTurret { + type="rotation"; + source="MainTurret"; + selection="bipod"; + sourceAddress = "loop"; + axis="rotate_axis"; + animPeriod=0.005; + minValue="rad -360"; + maxValue="rad +360"; + angle0="rad -360"; + angle1="rad +360"; + }; + class rest_rotate { + type="rotation"; + selection="grav_box"; + sourceAddress = "clamp"; + source="user"; + axis="elevate_axis"; + animPeriod=0.00001; + initPhase=-0.35; + maxValue="3.60"; + minValue="-3.60"; + angle1="rad -360"; + angle0="rad 360"; + }; + class optic_hide + { + type = "hide"; + source = "user"; + selection = "optic"; + animPeriod = 0.0001; + minValue = 0; + maxValue = 1; + minPhase = 0; + maxPhase = 1; + hideValue = 0.99; + initPhase = 1; + }; + class missile_hide + { + type = "hide"; + source = "user"; + selection = "missile"; + animPeriod = 0.0001; + minValue = 0; + maxValue = 1; + minPhase = 0; + maxPhase = 1; + hideValue = 0.99; + }; + }; + }; +}; diff --git a/addons/wep_dragon/models/ace_m47_magazine.p3d b/addons/wep_dragon/models/ace_m47_magazine.p3d new file mode 100644 index 0000000000..e8464fc389 Binary files /dev/null and b/addons/wep_dragon/models/ace_m47_magazine.p3d differ diff --git a/addons/wep_dragon/models/ace_m47_optic.p3d b/addons/wep_dragon/models/ace_m47_optic.p3d new file mode 100644 index 0000000000..839892f686 Binary files /dev/null and b/addons/wep_dragon/models/ace_m47_optic.p3d differ diff --git a/addons/wep_dragon/models/ace_m47_static.p3d b/addons/wep_dragon/models/ace_m47_static.p3d new file mode 100644 index 0000000000..15c4d5ef15 Binary files /dev/null and b/addons/wep_dragon/models/ace_m47_static.p3d differ diff --git a/addons/wep_dragon/models/dragon.p3d b/addons/wep_dragon/models/dragon.p3d new file mode 100644 index 0000000000..42ce5780f2 Binary files /dev/null and b/addons/wep_dragon/models/dragon.p3d differ diff --git a/addons/wep_dragon/script_component.hpp b/addons/wep_dragon/script_component.hpp new file mode 100644 index 0000000000..1898fac04c --- /dev/null +++ b/addons/wep_dragon/script_component.hpp @@ -0,0 +1,12 @@ +#define COMPONENT wep_dragon +#include "\z\ace\Addons\main\script_mod.hpp" + +#ifdef DEBUG_ENABLED_WEP_DRAGON + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_WEP_DRAGON + #define DEBUG_SETTINGS DEBUG_SETTINGS_WEP_DRAGON +#endif + +#include "\z\ace\Addons\main\script_macros.hpp" diff --git a/addons/wep_dragon/textures/dragon_text.paa b/addons/wep_dragon/textures/dragon_text.paa new file mode 100644 index 0000000000..a8a3787292 Binary files /dev/null and b/addons/wep_dragon/textures/dragon_text.paa differ diff --git a/addons/wep_dragon/textures/m47_daysight_item_ca.paa b/addons/wep_dragon/textures/m47_daysight_item_ca.paa new file mode 100644 index 0000000000..9768f42b9c Binary files /dev/null and b/addons/wep_dragon/textures/m47_daysight_item_ca.paa differ diff --git a/addons/wep_dragon/textures/m47_dragon_item_ca.paa b/addons/wep_dragon/textures/m47_dragon_item_ca.paa new file mode 100644 index 0000000000..0e87574794 Binary files /dev/null and b/addons/wep_dragon/textures/m47_dragon_item_ca.paa differ diff --git a/addons/wep_javelin/$PBOPREFIX$ b/addons/wep_javelin/$PBOPREFIX$ new file mode 100644 index 0000000000..9c5e79f2a1 --- /dev/null +++ b/addons/wep_javelin/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\Addons\wep_javelin \ No newline at end of file diff --git a/addons/wep_javelin/CfgEventhandlers.hpp b/addons/wep_javelin/CfgEventhandlers.hpp new file mode 100644 index 0000000000..70e16353cd --- /dev/null +++ b/addons/wep_javelin/CfgEventhandlers.hpp @@ -0,0 +1,17 @@ +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_pre_init)); + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_post_init)); + }; +}; + +class Extended_FiredBIS_EventHandlers { + class CAManBase { + ADDON = QUOTE(_this call FUNC(fired)); + }; +}; \ No newline at end of file diff --git a/addons/wep_javelin/CfgOptics.hpp b/addons/wep_javelin/CfgOptics.hpp new file mode 100644 index 0000000000..53f36710fb --- /dev/null +++ b/addons/wep_javelin/CfgOptics.hpp @@ -0,0 +1,50 @@ +class RscControlsGroup; +class RscPicture; +class RscMapControl; + +// Taken from AGM for optics management. + +class RscInGameUI { + class RscOptics_titan { + + class CA_javelin_elements_group: RscControlsGroup { + class Controls { + class CA_Javelin_Day_mode_off: RscPicture {}; + class CA_Javelin_SEEK_off: CA_Javelin_Day_mode_off { + idc = 1005; + }; + // From AGM + class GetLockedTarget: RscMapControl { + onDraw = QUOTE(_this call FUNC(onGetLockedTarget)); + idc = -1; + w = 0; + h = 0; + }; + }; + }; + }; +}; + +// on colorText[] = {0.2941, 0.8745, 0.2157, 1.0}; +// off colorText[] = {0.2941, 0.2941, 0.2941, 1.0}; +// orange colorText[] = {0.9255, 0.5216, 0.1216, 1.0}; + +/* +CA_javelin_elements_group: 170 +CA_Javelin_Day_mode_off: 1001 +CA_Javelin_Day_mode: 160 +CA_Javelin_WFOV_mode_off: 1004 +CA_Javelin_WFOV_mode_group: 163 +CA_Javelin_NFOV_mode_off: 1003 +CA_Javelin_NFOV_mode_group: 162 +CA_Javelin_SEEK_off: 1005 //1001 +CA_Javelin_SEEK: 166 +CA_Javelin_Missle_off: 1032 +CA_Javelin_Missle: 167 +CA_Javelin_CLU_off: 1027 +CA_Javelin_HangFire_off: 1028 +CA_Javelin_TOP_off: 1006 +CA_Javelin_DIR: 1007 +CA_Javelin_FLTR_mode_off: 1002 +CA_Javelin_FLTR_mode: 161 +*/ \ No newline at end of file diff --git a/addons/wep_javelin/XEH_post_init.sqf b/addons/wep_javelin/XEH_post_init.sqf new file mode 100644 index 0000000000..6904ee6c47 --- /dev/null +++ b/addons/wep_javelin/XEH_post_init.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" +NO_DEDICATED; + diff --git a/addons/wep_javelin/XEH_pre_init.sqf b/addons/wep_javelin/XEH_pre_init.sqf new file mode 100644 index 0000000000..8682a8a2e9 --- /dev/null +++ b/addons/wep_javelin/XEH_pre_init.sqf @@ -0,0 +1,4 @@ +#include "script_component.hpp" + +PREP(fired); +PREP(onGetLockedTarget); \ No newline at end of file diff --git a/addons/wep_javelin/config.cpp b/addons/wep_javelin/config.cpp new file mode 100644 index 0000000000..c47e95b44c --- /dev/null +++ b/addons/wep_javelin/config.cpp @@ -0,0 +1,14 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { "uo_main", "ace__laser", "a3_ui_f", "a3_weapons_f" }; + version = VERSION; + }; +}; + +#include "CfgEventhandlers.hpp" +#include "CfgOptics.hpp" \ No newline at end of file diff --git a/addons/wep_javelin/fnc_fired.sqf b/addons/wep_javelin/fnc_fired.sqf new file mode 100644 index 0000000000..d7f85691b2 --- /dev/null +++ b/addons/wep_javelin/fnc_fired.sqf @@ -0,0 +1,130 @@ +#define DEBUG_MODE_FULL +#include "script_component.hpp" +//_this=[TEST_AI_HELICOPTER,"missiles_DAGR","missiles_DAGR","Far_AI","M_PG_AT","24Rnd_PG_missiles",163988: rocket_01_fly_f.p3d] +TRACE_1("enter", _this); +PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + +FUNC(guidance_Javelin_LOBL_HI_PFH) = { + TRACE_1("enter", _this); + _args = _this select 0; + //PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + _shooter = _args select 0; + _missile = _args select 6; + _curVelocity = velocity _missile; + + if(!alive _missile || isNull _missile || isNull _shooter) exitWith { + [(_this select 1)] call cba_fnc_removePerFrameHandler; + }; + + TRACE_2("Setting launch parameters", GVAR(currentTarget), GVAR(currentTargetPos)); + _target = GVAR(currentTarget); + + _addHeight = [0,0,0]; + if(!isNil "_target") then { + + _yVec = vectorDir _missile; + _zVec = vectorUp _missile; + _xVec = vectorNormalized (_yVec vectorCrossProduct _zVec); + + _missilePos = getPosASL _missile; + // player sideChat "G!"; + _targetPos = GVAR(currentTargetPos); + + TRACE_4("Phase Check", _launchPos, _missilePos, _targetPos, (_missilePos distance _targetPos)); + if((count _targetPos) > 0) then { + _distanceToTarget = _missilePos vectorDistance _targetPos; + + _defPitch = 0.05; + + if((_launchPos distance _missilePos) < 400 && (_targetPos distance _missilePos) > 400) then { + _addHeight = [0,0,(_targetPos select 2) + ((_launchPos distance _targetPos)*2)]; + TRACE_1("Climb phase", _addHeight); + //_defPitch = 0.1; + } else { + // Covered half the distance, go terminal + if((_missilePos distance _targetPos) < (_launchPos distance _targetPos) / 2) then { + TRACE_1("TERMINAL", ""); + } else { + if((_missilePos select 2) > (_targetPos select 2)) then { + _heightDiff = (_missilePos select 2) - (_targetPos select 2); + TRACE_1("Coasting", _heightDiff); + _addHeight = [0,0, _heightDiff]; + }; + }; + }; + _targetPos = _targetPos vectorAdd _addHeight; + + _defYaw = 0.0035; + + + _targetVectorSeeker = [_missile, [_xVec, _yVec, _zVec], _targetPos] call FUNC(translateToWeaponSpace); + _yaw = 0.0; + if((_targetVectorSeeker select 0) < 0) then { + _yaw = -_defYaw; + } else { + if((_targetVectorSeeker select 0) > 0) then { + _yaw = _defYaw; + }; + }; + + _pitch = 0.0; + if((_targetVectorSeeker select 2) < 0) then { + _pitch = -_defPitch; + } else { + if((_targetVectorSeeker select 2) > 0) then { + _pitch = _defPitch; + }; + }; + #ifdef DEBUG_MODE_FULL + drawLine3D [(ASLtoATL _targetPos) vectorAdd _addHeight, ASLtoATL _targetPos, [0,1,0,1]]; + + _light = "#lightpoint" createVehicleLocal (getPos _missile); + _light setLightBrightness 1.0; + _light setLightAmbient [1.0, 0.0, 0.0]; + _light setLightColor [1.0, 0.0, 0.0]; + + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,1,1], ASLtoATL _missilePos, 0.75, 0.75, 0, str _vectorTo, 1, 0.025, "TahomaB"]; + drawLine3D [ASLtoATL _missilePos, ASLtoATL _targetPos, [1,0,0,1]]; + + _distance = ([getPos startPos, _missilePos] call BIS_fnc_distance2D); + _marker = createMarkerLocal [format["m%1", MARKERCOUNT], [_distance, _missilePos select 2]]; + _marker setMarkerTypeLocal "mil_dot"; + _marker setMarkerColorLocal "ColorRed"; + + MARKERCOUNT = MARKERCOUNT + 1; + #endif + + if(accTime > 0) then { + _outVector = [_missile, [_xVec, _yVec, _zVec], [_yaw, 1/accTime, _pitch]] call FUNC(translateToModelSpace); + + _vectorTo = _missilePos vectorFromTo _outVector; + _missile setVectorDirAndUp [_vectorTo, vectorUp _missile]; + }; + + #ifdef DEBUG_MODE_FULL + hintSilent format["d: %1", _distanceToTarget]; + #endif + }; + }; +}; + +FUNC(guidance_Javelin_LOBL_HI) = { + PARAMS_7(_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile); + + GVAR(lastTime) = time; + [FUNC(guidance_Javelin_LOBL_HI_PFH), 0, _this] call cba_fnc_addPerFrameHandler; +}; + +if(!local _shooter) exitWith { false }; +if(_weapon == "launch_B_Titan_short_F") then { + _fireMode = _shooter getVariable ["ACE_FIRE_SELECTION", ACE_DEFAULT_FIRE_SELECTION]; + + switch (_fireMode select 0) do { + // Default to FIREMODE_DIRECT_LOAL + // FIREMODE_DIRECT_LOAL + default { + LOG("Initiating Javelin FIREMODE_LOBL_HI"); + _this call FUNC(guidance_Javelin_LOBL_HI); + }; +}; +}; \ No newline at end of file diff --git a/addons/wep_javelin/fnc_onGetLockedTarget.sqf b/addons/wep_javelin/fnc_onGetLockedTarget.sqf new file mode 100644 index 0000000000..cd8609c7c8 --- /dev/null +++ b/addons/wep_javelin/fnc_onGetLockedTarget.sqf @@ -0,0 +1,8 @@ +#define DEBUG_MODE_FULL +#include "script_component.hpp" + +// Store the current cursor target for guidance +GVAR(currentTarget) = cursorTarget; +GVAR(currentTargetPos) = screenToWorld [0.5,0.5]; + +TRACE_2("Tracking optics target draw", GVAR(currentTarget), GVAR(currentTargetPos)); \ No newline at end of file diff --git a/addons/wep_javelin/script_component.hpp b/addons/wep_javelin/script_component.hpp new file mode 100644 index 0000000000..3c21d429f2 --- /dev/null +++ b/addons/wep_javelin/script_component.hpp @@ -0,0 +1,12 @@ +#define COMPONENT wep_javelin +#include "\z\ace\Addons\main\script_mod.hpp" + +#ifdef DEBUG_ENABLED_WEP_JAVELIN + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_WEP_JAVELIN + #define DEBUG_SETTINGS DEBUG_SETTINGS_WEP_JAVELIN +#endif + +#include "\z\ace\Addons\main\script_macros.hpp"