diff --git a/addons/missile_sdb/$PBOPREFIX$ b/addons/missile_sdb/$PBOPREFIX$ new file mode 100644 index 00000000000..c17a81095cb --- /dev/null +++ b/addons/missile_sdb/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\missile_sdb \ No newline at end of file diff --git a/addons/missile_sdb/CfgAmmo.hpp b/addons/missile_sdb/CfgAmmo.hpp new file mode 100644 index 00000000000..10bd2262c87 --- /dev/null +++ b/addons/missile_sdb/CfgAmmo.hpp @@ -0,0 +1,12 @@ +class EGVAR(missileguidance,type_Jdam); +class CfgAmmo { + class ammo_Bomb_SDB; + class GVAR(sdb): ammo_Bomb_SDB { + author = "Dani (TCVM)"; + maneuvrability = 0; // no maneuvrability so that default guidance doesnt work + class ace_missileguidance: EGVAR(missileguidance,type_Jdam) { + enabled = 1; + }; + }; +}; + diff --git a/addons/missile_sdb/CfgMagazines.hpp b/addons/missile_sdb/CfgMagazines.hpp new file mode 100644 index 00000000000..e0a88c9758b --- /dev/null +++ b/addons/missile_sdb/CfgMagazines.hpp @@ -0,0 +1,17 @@ +class CfgMagazines { + class magazine_Bomb_SDB_x1; + class PylonRack_Bomb_SDB_x4; + class GVAR(magazine_bomb_SDB_x1): magazine_Bomb_SDB_x1 { + displayName = CSTRING(39_1x); + author = "Dani (TCVM)"; + ammo = QGVAR(sdb); + }; + + class GVAR(PylonRack_bomb_SDB_x4): PylonRack_Bomb_SDB_x4 { + displayName = CSTRING(39_4x); + author = "Dani (TCVM)"; + ammo = QGVAR(sdb); + pylonWeapon = QGVAR(sdb); + }; +}; + diff --git a/addons/missile_sdb/CfgWeapons.hpp b/addons/missile_sdb/CfgWeapons.hpp new file mode 100644 index 00000000000..1d50c487a0d --- /dev/null +++ b/addons/missile_sdb/CfgWeapons.hpp @@ -0,0 +1,12 @@ +class CfgWeapons { + class weapon_SDBLauncher; + class GVAR(sdb): weapon_SDBLauncher { + author = "Dani (TCVM)"; + displayName = CSTRING(39); + magazines[] = { + QGVAR(magazine_bomb_SDB_x1), + QGVAR(PylonRack_bomb_SDB_x4) + }; + }; +}; + diff --git a/addons/missile_sdb/README.md b/addons/missile_sdb/README.md new file mode 100644 index 00000000000..5ac322e77b4 --- /dev/null +++ b/addons/missile_sdb/README.md @@ -0,0 +1,4 @@ +ace_missile_sdb +=================== + +Adds GBU-39 SDB diff --git a/addons/missile_sdb/config.cpp b/addons/missile_sdb/config.cpp new file mode 100644 index 00000000000..2313ddc12c5 --- /dev/null +++ b/addons/missile_sdb/config.cpp @@ -0,0 +1,20 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_common","ace_missileguidance"}; + author = ECSTRING(common,ACETeam); + authors[] = {"tcvm"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "CfgAmmo.hpp" +#include "CfgMagazines.hpp" +#include "CfgWeapons.hpp" + diff --git a/addons/missile_sdb/script_component.hpp b/addons/missile_sdb/script_component.hpp new file mode 100644 index 00000000000..726ffa5592e --- /dev/null +++ b/addons/missile_sdb/script_component.hpp @@ -0,0 +1,18 @@ +#define COMPONENT missile_sdb +#define COMPONENT_BEAUTIFIED Small Diameter Bomb +#include "\z\ace\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define ENABLE_PERFORMANCE_COUNTERS + +#ifdef DEBUG_ENABLED_MISSILE_SDB + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_MISSILE_SDB + #define DEBUG_SETTINGS DEBUG_SETTINGS_MISSILE_SDB +#endif + +#include "\z\ace\addons\main\script_macros.hpp" + diff --git a/addons/missile_sdb/stringtable.xml b/addons/missile_sdb/stringtable.xml new file mode 100644 index 00000000000..5e2e326cebd --- /dev/null +++ b/addons/missile_sdb/stringtable.xml @@ -0,0 +1,14 @@ + + + + + GBU-39 [ACE] + + + 1x GBU-39 [ACE] + + + 4x GBU-39 [ACE] + + + diff --git a/addons/missileguidance/ACE_GuidanceConfig.hpp b/addons/missileguidance/ACE_GuidanceConfig.hpp index f3c3b4b0c3e..2fff1d1ad5e 100644 --- a/addons/missileguidance/ACE_GuidanceConfig.hpp +++ b/addons/missileguidance/ACE_GuidanceConfig.hpp @@ -55,6 +55,14 @@ class GVAR(AttackProfiles) { functionName = QFUNC(attackProfile_BEAM); onFired = QFUNC(wire_onFired); // since Beam guidance is pretty much the same as Wire guidance, we can reuse this }; + class JDAM { + name = ""; + visualName = ""; + description = ""; + + functionName = QFUNC(attackProfile_JDAM); + onFired = QFUNC(gps_attackOnFired); + }; }; class GVAR(SeekerTypes) { @@ -96,6 +104,14 @@ class GVAR(SeekerTypes) { functionName = QFUNC(seekerType_MWR); onFired = QFUNC(mwr_onFired); }; + class GPS { + name = ""; + visualName = ""; + description = ""; + + functionName = QFUNC(seekerType_GPS); + onFired = QFUNC(gps_seekerOnFired); + }; class IR { name = ""; visualName = ""; diff --git a/addons/missileguidance/GPSDialog.hpp b/addons/missileguidance/GPSDialog.hpp new file mode 100644 index 00000000000..e6d383d38d6 --- /dev/null +++ b/addons/missileguidance/GPSDialog.hpp @@ -0,0 +1,247 @@ +#include "\a3\ui_f\hpp\defineCommonGrids.inc" +#include "\a3\ui_f\hpp\defineCommonColors.inc" +#include "idc_defines.hpp" + +class RscText; +class RscEdit; +class RscPicture; +class RscButton; +class ctrlXSliderH; + +class GVAR(gpsAttackOptionsUI) { + idd = -1; + movingEnable = 1; + enableSimulation = 1; + onLoad = QUOTE(_this call FUNC(gps_onLoad)); + onUnload = QUOTE(call FUNC(gps_onUnload)); + class controlsBackground { + class Header: RscText { + idc = -1; + text = CSTRING(GPS_ui_header); + x = QUOTE(13.5 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(5 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(18 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorBackground[] = GUI_BCG_COLOR; + moving = 1; + }; + class Background: RscText { + idd = -1; + x = QUOTE(13.5 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(6.1 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(18 * GUI_GRID_W); + h = QUOTE(8.0 * GUI_GRID_H); + colorBackground[] = {0, 0, 0, 0.8}; + }; + }; + class controls { + class TOOButton: RscButton { + idc = GPS_UI_TOO; + text = CSTRING(GPS_ui_too); + onButtonClick = QUOTE([GPS_UI_TOO] call FUNC(gps_modeSelect)); + x = QUOTE(14 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(6.3 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(10 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = GUI_BCG_COLOR; + colorFocused[] = {0, 0, 0, 0.8}; + }; + + class PPButton: RscButton { + idc = GPS_UI_PB; + text = CSTRING(GPS_ui_pp); + onButtonClick = QUOTE([GPS_UI_PB] call FUNC(gps_modeSelect)); + x = QUOTE(26 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(6.3 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(5 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = GUI_BCG_COLOR; + colorFocused[] = {0, 0, 0, 0.8}; + }; + + class PPMission: RscText { + idc = GPS_UI_PB_MISSION; + text = CSTRING(GPS_ui_pp_short); + onButtonClick = ""; + x = QUOTE(27.5 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(7.5 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(2 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 1}; + colorFocused[] = {0, 0, 0, 0.8}; + align = QUOTE(CENTER); + style = 2; + }; + + class PPMissionBackward: RscButton { + idc = GPS_UI_PB_MISSION_BACKWARD; + text = "<<"; + onButtonClick = QUOTE([-1] call FUNC(gps_pbModeCycle)); + x = QUOTE(26 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(7.5 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(1 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0.8}; + colorFocused[] = {0, 0, 0, 0.8}; + }; + + class PPMissionForward: RscButton { + idc = GPS_UI_PB_MISSION_FORWARD; + text = ">>"; + onButtonClick = QUOTE([1] call FUNC(gps_pbModeCycle)); + x = QUOTE(30 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(7.5 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(1 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0.8}; + colorFocused[] = {0, 0, 0, 0.8}; + }; + + class TargetPosXText: RscText { + idc = -1; + text = CSTRING(GPS_ui_easting); + x = QUOTE(14 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(8.5 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(3 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0}; + colorFocused[] = {0, 0, 0, 0.8}; + maxChars = 10; + }; + class TargetPosX: RscEdit { + idc = GPS_UI_EASTING; + text = ""; + x = QUOTE(17.3 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(8.5 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(2.5 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0.8}; + colorFocused[] = {0, 0, 0, 0.8}; + maxChars = 5; + }; + + class TargetPosYText: RscText { + idc = -1; + text = CSTRING(GPS_ui_northing); + x = QUOTE(14 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(9.7 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(3 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0}; + colorFocused[] = {0, 0, 0, 0.8}; + maxChars = 5; + }; + class TargetPosY: TargetPosX { + idc = GPS_UI_NORTHING; + x = QUOTE(17.3 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(9.7 * GUI_GRID_H + GUI_GRID_CENTER_Y); + }; + + class TargetPosHeightText: RscText { + idc = -1; + text = CSTRING(GPS_ui_altitude); + x = QUOTE(14 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(11.7 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(3 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0}; + colorFocused[] = {0, 0, 0, 0.8}; + maxChars = 5; + }; + class TargetPosHeight: TargetPosX { + idc = GPS_UI_HEIGHT; + x = QUOTE(17.3 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(11.7 * GUI_GRID_H + GUI_GRID_CENTER_Y); + }; + class TargetPosHeightUnits: RscText { + idc = -1; + text = "m"; + x = QUOTE(19.6 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(11.7 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(1 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0}; + colorFocused[] = {0, 0, 0, 0.8}; + maxChars = 5; + }; + + class ImpactAngleText: RscText { + idc = -1; + text = CSTRING(GPS_ui_impact_angle); + x = QUOTE(21 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(9.7 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(4 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0}; + colorFocused[] = {0, 0, 0, 0.8}; + maxChars = 5; + }; + class ImpactAngle: RscEdit { + idc = GPS_UI_ANGLE; + x = QUOTE(26.3 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(9.7 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(2 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + text = ""; + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0.8}; + colorFocused[] = {0, 0, 0, 0.8}; + maxChars = 2; + }; + + class AttackHeadingText: RscText { + idc = -1; + text = CSTRING(GPS_ui_attack_heading); + x = QUOTE(21 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(11 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(5 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0}; + colorFocused[] = {0, 0, 0, 0.8}; + maxChars = 5; + }; + class AttackHeading: RscEdit { + idc = GPS_UI_HEADING; + x = QUOTE(26.3 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(11 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(2 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + text = ""; + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0.8}; + colorFocused[] = {0, 0, 0, 0.8}; + maxChars = 3; + }; + + class CancelButton: RscButton { + idc = -1; + text = ECSTRING(common,cancel); + onButtonClick = QUOTE(closeDialog 0); + x = QUOTE(13.5 * GUI_GRID_W + GUI_GRID_CENTER_X); + y = QUOTE(14.2 * GUI_GRID_H + GUI_GRID_CENTER_Y); + w = QUOTE(5 * GUI_GRID_W); + h = QUOTE(GUI_GRID_H); + colorActive[] = {0, 0, 0, 1}; + colorBackground[] = {0, 0, 0, 0.8}; + colorFocused[] = {0, 0, 0, 0.8}; + }; + class ConfirmButton: CancelButton { + idc = IDC_TIMER_CONFIRM; + text = ECSTRING(common,confirm); + onButtonClick = QUOTE([] call FUNC(gps_confirm)); + x = QUOTE(27.5 * GUI_GRID_W + GUI_GRID_CENTER_X); + }; + }; +}; diff --git a/addons/missileguidance/XEH_PREP.hpp b/addons/missileguidance/XEH_PREP.hpp index 8e6cda1373c..66e4d2ce9b8 100644 --- a/addons/missileguidance/XEH_PREP.hpp +++ b/addons/missileguidance/XEH_PREP.hpp @@ -30,7 +30,7 @@ PREP(attackProfile_LIN); PREP(attackProfile_LOFT); PREP(attackProfile_WIRE); PREP(attackProfile_BEAM); -//re-enable after feature merge - PREP(attackProfile_JDAM); +PREP(attackProfile_JDAM); // Javelin profiles PREP(attackProfile_JAV_DIR); @@ -52,19 +52,33 @@ PREP(seekerType_SACLOS); PREP(seekerType_MCLOS); PREP(seekerType_Doppler); PREP(seekerType_MWR); +PREP(seekerType_GPS); PREP(seekerType_IR); // Attack Profiles OnFired PREP(wire_onFired); +PREP(gps_attackOnFired); // Seeker OnFired PREP(doppler_onFired); PREP(SACLOS_onFired); PREP(MCLOS_onFired); PREP(mwr_onFired); +PREP(gps_seekerOnFired); PREP(IR_onFired); // Navigation OnFired PREP(proNav_onFired); PREP(line_onFired); +// GPS ui +PREP(gps_onLoad); +PREP(gps_onUnload); +PREP(gps_pbModeCycle); +PREP(gps_confirm); +PREP(gps_modeSelect); +PREP(gps_saveAttackSettings); +PREP(gps_loadAttackSettings); +PREP(gps_getAttackData); +PREP(gps_setupVehicle); + diff --git a/addons/missileguidance/XEH_postInit.sqf b/addons/missileguidance/XEH_postInit.sqf index 1a8b37b5eb4..c85bd5aac29 100644 --- a/addons/missileguidance/XEH_postInit.sqf +++ b/addons/missileguidance/XEH_postInit.sqf @@ -6,9 +6,7 @@ ["ACE3 Weapons", QGVAR(cycleFireMode), LLSTRING(CycleFireMode), { [] call FUNC(cycleAttackProfileKeyDown) }, { -}, -[DIK_TAB, [false, true, false]], false] call CBA_fnc_addKeybind; //Ctrl+Tab Key - +}, [DIK_TAB, [false, true, false]], false] call CBA_fnc_addKeybind; //Ctrl+Tab Key // Each MCLOS argument is the vector which acceleration will be applied ["ACE3 Weapons", QGVAR(mclosUp), LLSTRING(mclosUp), { @@ -38,3 +36,19 @@ [[1, 0, 0], ACE_player] call FUNC(MCLOS_buttonPressed) }, [DIK_NUMPAD4, [false, false, false]], false, 0] call CBA_fnc_addKeybind; // Numpad 4 + +if (!hasInterface) exitWith {}; + +["ace_settingsInitialized", { + ["turret", LINKFUNC(gps_setupVehicle), false] call CBA_fnc_addPlayerEventHandler; + ["vehicle", LINKFUNC(gps_setupVehicle), true] call CBA_fnc_addPlayerEventHandler; // only one of these needs the retro flag + + // Add UAV Control Compatibility + ["ACE_controlledUAV", { + params ["_UAV", "_seatAI", "_turret", "_position"]; + TRACE_4("ACE_controlledUAV EH",_UAV,_seatAI,_turret,_position); + if (!isNull _seatAI) then { + [_seatAI] call FUNC(gps_setupVehicle); + }; + }] call CBA_fnc_addEventHandler; +}] call CBA_fnc_addEventHandler; diff --git a/addons/missileguidance/XEH_preInit.sqf b/addons/missileguidance/XEH_preInit.sqf index 9b1a85e37c7..b6a465d9451 100644 --- a/addons/missileguidance/XEH_preInit.sqf +++ b/addons/missileguidance/XEH_preInit.sqf @@ -11,6 +11,21 @@ PREP_RECOMPILE_END; // As weapons take config changes, there is little point in being able to disable guidance if (isNil QGVAR(enabled)) then { GVAR(enabled) = 2; }; +GVAR(gps_currentSettings) = [ + [0, 0, 0], // attack position + -1, // impact angle + -1 // attack heading +]; + +GVAR(gps_pbMode) = 0; +GVAR(gps_settings) = createHashMap; +for "_i" from 0 to MAX_PB_MODES do { + GVAR(gps_settings) set [_i, GVAR(currentSettings)]; +}; + +GVAR(gps_mode) = "pb"; +GVAR(gps_weapons) = createHashMap; + GVAR(debug_enableMissileCamera) = false; GVAR(debug_drawGuidanceInfo) = false; diff --git a/addons/missileguidance/config.cpp b/addons/missileguidance/config.cpp index 2b4a597c476..bab2502fb6d 100644 --- a/addons/missileguidance/config.cpp +++ b/addons/missileguidance/config.cpp @@ -21,7 +21,7 @@ class CfgPatches { #include "CfgAmmo.hpp" #include "CfgMagazines.hpp" #include "CfgWeapons.hpp" +#include "GPSDialog.hpp" #ifdef CREATE_MOCK_PLATFORMS #include "dev\mock_vehicles.hpp" -#endif - +#endif \ No newline at end of file diff --git a/addons/missileguidance/functions/fnc_attackProfile_JDAM.sqf b/addons/missileguidance/functions/fnc_attackProfile_JDAM.sqf new file mode 100644 index 00000000000..b10ece08dc4 --- /dev/null +++ b/addons/missileguidance/functions/fnc_attackProfile_JDAM.sqf @@ -0,0 +1,60 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Attack profile: JDAM + * Uses LINE navigation type to guide projectile onto target + * + * Arguments: + * 0: Seeker Target PosASL + * 1: Guidance Arg Array + * 2: Seeker State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_jdam; + * + * Public: No + */ +params ["_seekerTargetPos", "_args", "_attackProfileStateParams", "_timestep"]; +_args params ["_firedEH", "", "_flightParams", "", "", "_targetData"]; +_firedEH params ["_shooter","","","","","","_projectile"]; +_attackProfileStateParams params ["_gpsData", "_initialProjectileHeight", "_terminal"]; +_gpsData params ["", "_impactAngle", "_attackDirection"]; +_targetData params ["_directionToTarget", "", "_distanceToTarget"]; +_flightParams params ["_pitchRate", "_yawRate"]; + +if (_impactAngle <= 0) then { + _impactAngle = 45; // immediate pitch over to attack +}; + +if (_attackDirection < 0) then { + _attackDirection = direction _projectile; + _gpsData set [2, _attackDirection]; +}; + +private _projectilePos = getPosASLVisual _projectile; +private _lineDir = [1, 180 + _attackDirection, _impactAngle] call CBA_fnc_polar2vect; + +private _leadDistance = linearConversion [0, 1000, _projectilePos vectorDistance _seekerTargetPos, 5, 500, true]; + +private _missilePosProjected = _seekerTargetPos vectorAdd (_lineDir vectorMultiply ((_projectilePos vectorDistance _seekerTargetPos) - _leadDistance)); +// don't climb +if (_missilePosProjected#2 > _projectilePos#2) then { + _missilePosProjected set [2, _projectilePos#2]; +}; +_targetData set [2, (_projectilePos vectorDistance _missilePosProjected)]; + +if (GVAR(debug_drawGuidanceInfo)) then { + private _projectilePitch = ((vectorDir _projectile) call CBA_fnc_vect2polar) select 2; + //IGNORE_PRIVATE_WARNING ["_attackProfileName"]; + _attackProfileName = format ["JDAM [Pitch - %1 Impact Pitch - %2]", _projectilePitch, _impactAngle]; + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,0,1], ASLToAGL _missilePosProjected, 0.75, 0.75, 0, "P", 1, 0.025, "TahomaB"]; + private _desiredAngle = _lineDir vectorMultiply 5000; + private _targetPosAGL = ASLToAGL _seekerTargetPos; + drawLine3D [_targetPosAGL, _targetPosAGL vectorAdd _desiredAngle, [1, 1, 1, 1]]; +}; + +_missilePosProjected + diff --git a/addons/missileguidance/functions/fnc_gps_attackOnFired.sqf b/addons/missileguidance/functions/fnc_gps_attackOnFired.sqf new file mode 100644 index 00000000000..677148e4fbb --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_attackOnFired.sqf @@ -0,0 +1,23 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Sets up wireGuided state arrays (called from missileGuidance's onFired). + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * None + * + * Example: + * [] call ace_missileguidance_fnc_gps_attackOnFired + * + * Public: No + */ +params ["_firedEH", "", "", "", "_stateParams", "", ""]; +_stateParams params ["", "", "_attackProfileStateParams"]; +_firedEH params ["_shooter","","","","_ammo","","_projectile"]; + +_attackProfileStateParams set [0, [] call FUNC(gps_getAttackData)]; +_attackProfileStateParams set [1, (getPosASL _projectile) select 2]; +_attackProfileStateParams set [2, false]; diff --git a/addons/missileguidance/functions/fnc_gps_confirm.sqf b/addons/missileguidance/functions/fnc_gps_confirm.sqf new file mode 100644 index 00000000000..eeb440587bc --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_confirm.sqf @@ -0,0 +1,21 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Confirm GPS weapon settings and serialize to variables + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * None + * + * Example: + * [] call ace_missileguidance_fnc_gps_confirm + * + * Public: No + */ +if (GVAR(gps_mode) isEqualTo "pb") then { + [GVAR(gps_pbMode)] call FUNC(gps_saveAttackSettings); +}; +closeDialog 0; + diff --git a/addons/missileguidance/functions/fnc_gps_getAttackData.sqf b/addons/missileguidance/functions/fnc_gps_getAttackData.sqf new file mode 100644 index 00000000000..7101cefd9fb --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_getAttackData.sqf @@ -0,0 +1,26 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Returns attack data for GPS guided bomb + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * [] call ace_missileguidance_fnc_gps_getAttackData + * + * Public: No + */ + +if (GVAR(gps_mode) isEqualTo "too") then { + private _target = getPilotCameraTarget (vehicle ACE_PLAYER); + _target params ["_tracking", "_position", "_object"]; + GVAR(gps_currentSettings) set [0, _position] +}; + +// create a copy of this array to make sure values are not overwritten ++GVAR(gps_currentSettings) // return + diff --git a/addons/missileguidance/functions/fnc_gps_loadAttackSettings.sqf b/addons/missileguidance/functions/fnc_gps_loadAttackSettings.sqf new file mode 100644 index 00000000000..adff47c376f --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_loadAttackSettings.sqf @@ -0,0 +1,53 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Saves all textboxes to whatever settings say for PB mode + * + * Arguments: + * Current PB mode + * + * Return Value: + * None + * + * Example: + * [] call ace_missileguidance_fnc_gps_saveAttackSettings + * + * Public: No + */ +params ["_mode"]; +private _display = uiNamespace getVariable QGVAR(gpsAttackOptionDisplay); + +private _settings = GVAR(gps_settings) get _mode; + +_settings params ["_position", "_angle", "_heading"]; +private _height = _position select 2; + +private _grid = [_position] call EFUNC(common,getMapGridFromPos); +_grid params ["_easting", "_northing"]; + +if (_angle < 0) then { + _angle = ""; +} else { + _angle = str _angle; +}; + +if (_heading < 0) then { + _heading = ""; +} else { + _heading = str _heading; +}; + +if (0 == parseNumber _easting) then { + _easting = ""; +}; + +if (0 == parseNumber _northing) then { + _northing = ""; +}; + +(_display displayCtrl GPS_UI_EASTING) ctrlSetText _easting; +(_display displayCtrl GPS_UI_NORTHING) ctrlSetText _northing; +(_display displayCtrl GPS_UI_HEIGHT) ctrlSetText str _height; +(_display displayCtrl GPS_UI_ANGLE) ctrlSetText _angle; +(_display displayCtrl GPS_UI_HEADING) ctrlSetText _heading; + diff --git a/addons/missileguidance/functions/fnc_gps_modeSelect.sqf b/addons/missileguidance/functions/fnc_gps_modeSelect.sqf new file mode 100644 index 00000000000..ef7d4ecbe75 --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_modeSelect.sqf @@ -0,0 +1,56 @@ +#include "..\script_component.hpp" +#include "\a3\ui_f\hpp\defineCommonColors.inc" +/* + * Author: tcvm + * Select either TOO or PB mode. Disable anything that shouldnt be touched in TOO and renable in PB + * + * Arguments: + * Mode to switch to + * + * Return Value: + * None + * + * Example: + * [0] call ace_missileguidance_fnc_gps_modeSelect + * + * Public: No + */ +params ["_mode", ["_onLoad", false]]; +private _display = uiNamespace getVariable QGVAR(gpsAttackOptionDisplay); + +{ + // only TOO and PB modes modelled + if (_mode == GPS_UI_TOO) then { + // disable + ctrlEnable [_x, false]; + } else { + // enable + ctrlEnable [_x, true]; + }; +} forEach CONTROLS_DISABLED_IN_TOO; + +private _backgroundColour = [ + GUI_BCG_RGB_R call BIS_fnc_parseNumber, + GUI_BCG_RGB_G call BIS_fnc_parseNumber, + GUI_BCG_RGB_B call BIS_fnc_parseNumber, + GUI_BCG_ALPHA call BIS_fnc_parseNumber +]; + +private _selectedColour = [ + 0, + 0, + 0, + 1 +]; + +ctrlSetFocus (_display displayCtrl _mode); +if (_mode == GPS_UI_TOO) then { + GVAR(gps_mode) = "too"; + if !(_onLoad) then { + [GVAR(gps_pbMode)] call FUNC(gps_saveAttackSettings); + }; +} else { + GVAR(gps_mode) = "pb"; + [GVAR(gps_pbMode)] call FUNC(gps_loadAttackSettings); +}; + diff --git a/addons/missileguidance/functions/fnc_gps_onLoad.sqf b/addons/missileguidance/functions/fnc_gps_onLoad.sqf new file mode 100644 index 00000000000..a35e1d4cdaa --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_onLoad.sqf @@ -0,0 +1,50 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Called on load of GPS UI + * + * Arguments: + * Display + * + * Return Value: + * None + * + * Example: + * [1] call ace_missileguidance_fnc_gps_onLoad + * + * Public: No + */ +[{ + params ["_display"]; + TRACE_1("gps_onLoad",_display); + uiNamespace setVariable [QGVAR(gpsAttackOptionDisplay), _display]; + + private _mode = [GPS_UI_PB, GPS_UI_TOO] select (GVAR(gps_mode) isEqualTo "too"); + + [_mode, true] call FUNC(gps_modeSelect); + (_display displayCtrl GPS_UI_PB_MISSION) ctrlSetText format ["%1 %2", localize LSTRING(GPS_ui_pp_short), GVAR(gps_pbMode) + 1]; + + // update current settings + GVAR(gps_uiPerFrameHandler) = [{ + if (GVAR(gps_mode) isEqualTo "too") then { + // update coordinates based on TGP position + private _target = getPilotCameraTarget (vehicle ACE_PLAYER); + _target params ["_tracking", "_position", "_object"]; + + if (_position isNotEqualTo [0, 0, 0]) then { + private _mapGrid = [_position] call EFUNC(common,getMapGridFromPos); + _mapGrid params ["_easting", "_northing"]; + private _height = _position#2; + + private _display = uiNamespace getVariable QGVAR(gpsAttackOptionDisplay); + (_display displayCtrl GPS_UI_EASTING) ctrlSetText _easting; + (_display displayCtrl GPS_UI_NORTHING) ctrlSetText _northing; + (_display displayCtrl GPS_UI_HEIGHT) ctrlSetText str _height; + }; + }; + + // info is read from text boxes, so if boxes are update this will be updated + GVAR(gps_currentSettings) = [-1] call FUNC(gps_saveAttackSettings); + }] call CBA_fnc_addPerFrameHandler; +}, _this] call CBA_fnc_execNextFrame; + diff --git a/addons/missileguidance/functions/fnc_gps_onUnload.sqf b/addons/missileguidance/functions/fnc_gps_onUnload.sqf new file mode 100644 index 00000000000..fbde5fbaef1 --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_onUnload.sqf @@ -0,0 +1,18 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Called on unload of GPS UI + * + * Arguments: + * Display + * + * Return Value: + * None + * + * Example: + * [] call ace_missileguidance_fnc_gps_onUnload + * + * Public: No + */ +[GVAR(gps_uiPerFrameHandler)] call CBA_fnc_removePerFrameHandler; + diff --git a/addons/missileguidance/functions/fnc_gps_pbModeCycle.sqf b/addons/missileguidance/functions/fnc_gps_pbModeCycle.sqf new file mode 100644 index 00000000000..ba7256b3212 --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_pbModeCycle.sqf @@ -0,0 +1,36 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Cycle pre-briefed mission mode + * + * Arguments: + * Direction + * + * Return Value: + * None + * + * Example: + * [1] call ace_missileguidance_fnc_gps_pbModeCycle + * + * Public: No + */ +params ["_direction"]; +private _display = uiNamespace getVariable QGVAR(gpsAttackOptionDisplay); + +[GVAR(gps_pbMode)] call FUNC(gps_saveAttackSettings); + +if (_direction > 0) then { + // right + GVAR(gps_pbMode) = (GVAR(gps_pbMode) + 1) % MAX_PB_MODES +} else { + // left + GVAR(gps_pbMode) = (GVAR(gps_pbMode) - 1); + if (GVAR(gps_pbMode) < 0) then { + GVAR(gps_pbMode) = MAX_PB_MODES - 1; + }; + GVAR(gps_pbMode) = GVAR(gps_pbMode) % MAX_PB_MODES; +}; + +[GVAR(gps_pbMode)] call FUNC(gps_loadAttackSettings); +(_display displayCtrl GPS_UI_PB_MISSION) ctrlSetText format ["%1 %2", localize LSTRING(GPS_ui_pp_short), GVAR(gps_pbMode) + 1]; + diff --git a/addons/missileguidance/functions/fnc_gps_saveAttackSettings.sqf b/addons/missileguidance/functions/fnc_gps_saveAttackSettings.sqf new file mode 100644 index 00000000000..d25ff1b8ccb --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_saveAttackSettings.sqf @@ -0,0 +1,65 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Saves all textboxes to whatever settings say for PB mode + * + * Arguments: + * Current PB mode. If -1 no mode is used + * + * Return Value: + * current settings + * + * Example: + * [-1] call ace_missileguidance_fnc_gps_saveAttackSettings + * + * Public: No + */ +params ["_mode"]; +private _display = uiNamespace getVariable QGVAR(gpsAttackOptionDisplay); + +private _easting = ctrlText (_display displayCtrl GPS_UI_EASTING); +private _northing = ctrlText (_display displayCtrl GPS_UI_NORTHING); +private _height = ctrlText (_display displayCtrl GPS_UI_HEIGHT); +private _angle = ctrlText (_display displayCtrl GPS_UI_ANGLE); +private _heading = ctrlText (_display displayCtrl GPS_UI_HEADING); + +if (_height isEqualTo "") then { + _height = 0 +} else { + _height = parseNumber _height; +}; + +if (_angle isEqualTo "") then { + _angle = -1 +} else { + _angle = parseNumber _angle; +}; + +if (_heading isEqualTo "") then { + _heading = -1 +} else { + _heading = parseNumber _heading; +}; + +private _minGridCount = (count _easting) min (count _northing); + +private _grid = (_easting select [0, _minGridCount]) + (_northing select [0, _minGridCount]); +private _position = if (_grid isEqualTo "") then { + [0, 0, 0] +} else { + [_grid, false] call EFUNC(common,getMapPosFromGrid); +}; +_position set [2, _height]; + +TRACE_3("settings gps pos",_position,_angle,_heading); + +private _settings = [ + _position, // attack position + _angle, // impact angle + _heading // attack heading +]; + +if (_mode != -1) then { + GVAR(gps_settings) set [_mode, _settings]; +}; +_settings diff --git a/addons/missileguidance/functions/fnc_gps_seekerOnFired.sqf b/addons/missileguidance/functions/fnc_gps_seekerOnFired.sqf new file mode 100644 index 00000000000..575df64d9a5 --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_seekerOnFired.sqf @@ -0,0 +1,20 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Sets up wireGuided state arrays (called from missileGuidance's onFired). + * + * Arguments: + * Guidance Arg Array + * + * Return Value: + * None + * + * Example: + * [] call ace_missileguidance_fnc_gps_seekerOnFired + * + * Public: No + */ +params ["", "", "", "", "_stateParams", "", ""]; +_stateParams params ["", "_seekerStateParams"]; + +_seekerStateParams set [0, [] call FUNC(gps_getAttackData)]; diff --git a/addons/missileguidance/functions/fnc_gps_setupVehicle.sqf b/addons/missileguidance/functions/fnc_gps_setupVehicle.sqf new file mode 100644 index 00000000000..72dffe06492 --- /dev/null +++ b/addons/missileguidance/functions/fnc_gps_setupVehicle.sqf @@ -0,0 +1,47 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Adds interaction menu actions to configure GPS bombs + * + * Arguments: + * 0: Player + * + * Return Value: + * Nothing + * + * Example: + * [player] call ace_missileguidance_fnc_gps_setupVehicle + * + * Public: No + */ +params ["_player"]; +private _vehicle = vehicle _player; + +if (_vehicle getVariable [QGVAR(gps_actionsAdded), false]) exitWith {}; +_vehicle setVariable [QGVAR(gps_actionsAdded), true]; +TRACE_2("adding gps action",_player,typeOf _vehicle); + +private _condition = { + params ["_target", "_player"]; // _player may be the UAV AI + + private _turretPath = if (_player == (driver _target)) then {[-1]} else {_player call CBA_fnc_turretPath}; + private _hasJDAM = (_target weaponsTurret _turretPath) findIf { + private _weapon = _x; + GVAR(gps_weapons) getOrDefaultCall [_weapon, { + (getArray (configFile >> "CfgWeapons" >> _weapon >> "magazines")) findIf { + private _ammo = getText (configFile >> "CfgMagazines" >> _x >> "ammo"); + private _ammoAttackProfiles = getArray (configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON) >> "attackProfiles"); + "JDAM" in _ammoAttackProfiles + } > -1 + }, true] + } > -1; + _hasJDAM +}; + +private _statement = { + createDialog QGVAR(gpsAttackOptionsUI); +}; + +private _action = [QUOTE(ADDON), "JDAM settings", "", _statement, _condition] call EFUNC(interact_menu,createAction); +[_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject); + diff --git a/addons/missileguidance/functions/fnc_seekerType_GPS.sqf b/addons/missileguidance/functions/fnc_seekerType_GPS.sqf new file mode 100644 index 00000000000..01b011f9a65 --- /dev/null +++ b/addons/missileguidance/functions/fnc_seekerType_GPS.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Returns GPS position. That's it. + * + * Arguments: + * 1: Guidance Arg Array + * 2: Seeker State + * + * Return Value: + * Position of wanted missile pos relative to the camera direction + * + * Example: + * [] call ace_missileguidance_fnc_seekerType_gps + * + * Public: No + */ +params ["", "_args", "_seekerStateParams"]; +_args params ["", "", "", "", "", "_targetData"]; +(_seekerStateParams select 0) params ["_attackPosition"]; +//IGNORE_PRIVATE_WARNING ["_projectile"]; + +_targetData set [0, (getPosASL _projectile) vectorFromTo _attackPosition]; +_targetData set [2, (getPosASL _projectile) distance _attackPosition]; +_targetData set [3, [0, 0, 0]]; +_targetData set [4, [0, 0, 0]]; + +_attackPosition + diff --git a/addons/missileguidance/idc_defines.hpp b/addons/missileguidance/idc_defines.hpp new file mode 100644 index 00000000000..80bcda938fb --- /dev/null +++ b/addons/missileguidance/idc_defines.hpp @@ -0,0 +1,34 @@ +#ifndef GPS_UI_TOO +#define GPS_UI_TOO 1704211 +#endif +#ifndef GPS_UI_PB +#define GPS_UI_PB 1704112 +#endif +#ifndef GPS_UI_PB_MISSION +#define GPS_UI_PB_MISSION 1704113 +#endif +#ifndef GPS_UI_PB_MISSION_BACKWARD +#define GPS_UI_PB_MISSION_BACKWARD 1704114 +#endif +#ifndef GPS_UI_PB_MISSION_FORWARD +#define GPS_UI_PB_MISSION_FORWARD 1704115 +#endif +#ifndef GPS_UI_EASTING +#define GPS_UI_EASTING 1704116 +#endif +#ifndef GPS_UI_NORTHING +#define GPS_UI_NORTHING 1704117 +#endif +#ifndef GPS_UI_HEIGHT +#define GPS_UI_HEIGHT 1704118 +#endif +#ifndef GPS_UI_ANGLE +#define GPS_UI_ANGLE 1704119 +#endif +#ifndef GPS_UI_HEADING +#define GPS_UI_HEADING 1704120 +#endif +#ifndef IDC_TIMER_CONFIRM +#define IDC_TIMER_CONFIRM 1704121 +#endif + diff --git a/addons/missileguidance/script_component.hpp b/addons/missileguidance/script_component.hpp index ebd3fb30a45..2d446d3e0af 100644 --- a/addons/missileguidance/script_component.hpp +++ b/addons/missileguidance/script_component.hpp @@ -30,3 +30,9 @@ #define DEFAULT_LEAD_DISTANCE 5 #define ACTIVE_RADAR_POLL_FREQUENCY (1 / 7) #define ACTIVE_RADAR_MINIMUM_SCAN_AREA 30 + +#include "idc_defines.hpp" +#define CONTROLS_DISABLED_IN_TOO [GPS_UI_PB_MISSION_BACKWARD, GPS_UI_PB_MISSION_FORWARD, GPS_UI_EASTING, GPS_UI_NORTHING, GPS_UI_HEIGHT] + +#define MAX_PB_MODES 6 + diff --git a/addons/missileguidance/stringtable.xml b/addons/missileguidance/stringtable.xml index 4eb4bff000e..634e2169847 100644 --- a/addons/missileguidance/stringtable.xml +++ b/addons/missileguidance/stringtable.xml @@ -35,6 +35,33 @@ Gelişmiş füze rehberliği veya AMG, füze kilitleme ve ateşleme için çoklu geliştirmeler sağlar. A fejlett rakétairányító (vagy AMG) többféle módosítást tartalmaz a rakéták célkövetéséhez és tüzeléséhez. Ez egy szükséges keresztrendszer a rakéta-alapú fegyverekhez. + + Altitude + + + Attack Heading + + + Easting + + + GPS Weapon Setup + + + Impact Angle + + + Northing + + + PRE-PLANNED + + + PP + + + TARGET OF OPPORTUNITY + Hellfire II AGM-114K Missile Hellfire II AGM-114K