diff --git a/addons/missile_clgp/ACE_GuidanceConfig.hpp b/addons/missile_clgp/ACE_GuidanceConfig.hpp index e69de29bb2d..f32e29af2a1 100644 --- a/addons/missile_clgp/ACE_GuidanceConfig.hpp +++ b/addons/missile_clgp/ACE_GuidanceConfig.hpp @@ -0,0 +1,6 @@ +class EGVAR(missileguidance,AttackProfiles) { + class copperhead { + onFired = QFUNC(copperhead_onfired); + functionName = QFUNC(copperhead_attackprofile); + }; +}; diff --git a/addons/missile_clgp/CfgAmmo.hpp b/addons/missile_clgp/CfgAmmo.hpp index 12b153dccc7..9847b5b9048 100644 --- a/addons/missile_clgp/CfgAmmo.hpp +++ b/addons/missile_clgp/CfgAmmo.hpp @@ -1,8 +1,109 @@ class CfgAmmo { class SubmunitionBase; + class ace_155mm_m712_launch: SubmunitionBase { + model = "\A3\weapons_f\ammo\shell"; + hit = 1200; + indirectHit = 200; + indirectHitRange = 4; + EGVAR(frag,force) = 1; + EGVAR(frag,skip) = 0; + EGVAR(frag,charge) = 9979; + EGVAR(frag,metal) = 36000; + EGVAR(frag,gurney_c) = 2700; + EGVAR(frag,gurney_k) = 0.5; + EGVAR(frag,classes)[] = {QEGVAR(frag,small), QEGVAR(frag,small_HD), QEGVAR(frag,medium), QEGVAR(frag,medium_HD), QEGVAR(frag,large_HD)}; + + GVAR(artilleryDrag) = 1; + GVAR(deployCondition) = QFUNC(copperhead_deployCondition); + submunitionAmmo = "ace_155mm_m712_guidance"; + submunitionCount = 1; + submunitionConeAngle = 0; + triggerDistance = 0; + muzzleEffect = ""; + airFriction = 0; + + class Eventhandlers { + fired = QUOTE(call FUNC(submunition_ammoFired)); + }; + class CamShakeFire { + power = 3.00922; + duration = 1.8; + frequency = 20; + distance = 72.4431; + }; + class CamShakePlayerFire { + power = 0.01; + duration = 0.1; + frequency = 20; + distance = 1; + }; + }; + + class ammo_Bomb_LaserGuidedBase; + class ace_155mm_m712_guidance: ammo_Bomb_LaserGuidedBase { + model = "\A3\Weapons_F_beta\Launchers\titan\titan_missile_at_fly"; + hit = 1200; + indirectHit = 200; + indirectHitRange = 4; + EGVAR(frag,skip) = 0; + EGVAR(frag,charge) = 9979; + EGVAR(frag,metal) = 36000; + EGVAR(frag,gurney_c) = 2440; + EGVAR(frag,gurney_k) = "1/2"; + EGVAR(frag,classes)[] = {QEGVAR(frag,large), QEGVAR(frag,large), QEGVAR(frag,large_HD), QEGVAR(frag,large), QEGVAR(frag,huge), QEGVAR(frag,huge_HD), QEGVAR(frag,huge)}; + + maneuvrability = 0; + airFriction = 0.01; // note: works differently from shellsim (v^3...) + sideAirFriction = 0.1; + + artilleryLock = 0; // would keep shell pointed towards velocity, but disables manuverability and airfric + + initTime = 0; + thrustTime = 0; + thrust = 0; // free fall + + manualControl = 0; + flightProfiles[] = {}; + autoSeekTarget = 0; + weaponLockSystem = 0; + irLock = 0; + laserLock = 0; + airLock = 0; + timeToLive = 200; + class ace_missileguidance { + enabled = 2; + pitchRate = 10; // replace minDeflection, maxDeflection, incDeflection + yawRate = 10; + stabilityCoefficient = 0.2; // helps make the shot follow velocity + // Guidance type for munitions + defaultSeekerType = "SALH"; + seekerTypes[] = { "SALH" }; + + defaultSeekerLockMode = "LOAL"; + seekerLockModes[] = { "LOAL" }; + + defaultNavigationType = "Direct"; + navigationTypes[] = { "Direct" }; + + seekerAngle = 70; // Angle in front of the missile which can be searched + seekerAccuracy = 1; // seeker accuracy multiplier + + seekerMinRange = 0; + seekerMaxRange = 3000; // Range from the missile which the seeker can visually search + + seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos] + + // Attack profile type selection + defaultAttackProfile = "copperhead"; + attackProfiles[] = {"copperhead"}; + useModeForAttackProfile = 0; + canVanillaLock = 0; + }; + }; + class GVAR(pike_launch): SubmunitionBase { model = QPATHTOF(data\ace_pike_ammo.p3d); submunitionAmmo = QGVAR(pike_guidance); diff --git a/addons/missile_clgp/CfgMagazineWells.hpp b/addons/missile_clgp/CfgMagazineWells.hpp index e5ccc8b0749..c3b0e8f70b6 100644 --- a/addons/missile_clgp/CfgMagazineWells.hpp +++ b/addons/missile_clgp/CfgMagazineWells.hpp @@ -1,4 +1,11 @@ class CfgMagazineWells { + class ACE_155mm_artillery { + ADDON[] = {"ace_1rnd_155mm_m712", "ace_8rnd_155mm_m712"}; + }; + class gm_magazineWell_155mm { + // gm magwells are misconfigured (extra s on weapon cfg `magazineWells[]` so it does nothing) + ADDON[] = {"ace_1rnd_155mm_m712", "ace_8rnd_155mm_m712"}; + }; class CBA_40mm_EGLM { // for longer grenades that can only fit side breech-loading ADDON[] = {"ACE_40mm_Pike"}; }; diff --git a/addons/missile_clgp/CfgMagazines.hpp b/addons/missile_clgp/CfgMagazines.hpp index 99886a2a938..c965dc8d70d 100644 --- a/addons/missile_clgp/CfgMagazines.hpp +++ b/addons/missile_clgp/CfgMagazines.hpp @@ -1,4 +1,19 @@ class CfgMagazines { + class 32Rnd_155mm_Mo_shells; + class ace_1rnd_155mm_m712: 32Rnd_155mm_Mo_shells { + author = ECSTRING(common,ACETeam); + displayNameMFDFormat = "M712"; + displayNameShort = "M712"; + displayName = "Copperhead"; + ammo = "ace_155mm_m712_launch"; + count = 1; + GVAR(copperheadInterface) = 1; + muzzleImpulseFactor[]={0.5,1}; // needed for compat with other mods (cup howitzer goes flying) + }; + class ace_8rnd_155mm_m712: ace_1rnd_155mm_m712 { + count = 8; + }; + class 1Rnd_HE_Grenade_shell; class ACE_40mm_Pike: 1Rnd_HE_Grenade_shell { author = ECSTRING(common,ACETeam); diff --git a/addons/missile_clgp/CfgWeapons.hpp b/addons/missile_clgp/CfgWeapons.hpp index e69de29bb2d..eb21bfa28fa 100644 --- a/addons/missile_clgp/CfgWeapons.hpp +++ b/addons/missile_clgp/CfgWeapons.hpp @@ -0,0 +1,8 @@ +class CfgWeapons { + class CannonCore; + class mortar_155mm_AMOS: CannonCore { + magazineWell[] += {"ACE_155mm_artillery"}; + // reloadTime = 1; // dev + // magazineReloadTime = 1; + }; +}; diff --git a/addons/missile_clgp/GUI.hpp b/addons/missile_clgp/GUI.hpp index e69de29bb2d..1257bb899e4 100644 --- a/addons/missile_clgp/GUI.hpp +++ b/addons/missile_clgp/GUI.hpp @@ -0,0 +1,92 @@ +class RscObject; +class RscButton; + +class GVAR(copperhead_dialButton): RscButton { + style = 2; + x = 0; + y = 0; + w = 99; + h = 99; + soundEnter[] = {"", 0.2, 1}; + soundPush[] = {"", 0.2, 1}; + soundClick[] = {"", 0.2, 1}; + soundEscape[] = {"", 0.2, 1}; + color[] = {0,0,0,0}; + colorBackground[] = {0,0,1,0}; + // colorBackground[] = {0,0,1,0.1}; + colorBackgroundDisabled[] = {0,0,0,0}; + colorBackgroundActive[] = {0,0,0,0}; + colorFocused[] = {0,0,0,0}; + text = ""; +}; + +class GVAR(copperhead_dialog) { + idd = -1; + enableSimulation = 1; + onLoad = QUOTE(with uiNamespace do {GVAR(copperhead_dialog) = _this select 0}); + duration = 1e99; + class ControlsBackground {}; + class Controls {}; + class Objects { + class TheThing: RscObject { + type = 82; + idc = 100; + model = QPATHTOF(data\ace_copperhead_interactive.p3d); + direction[] = {0,0,1}; + up[] = {0,1,0}; + position[] = {0,-0.338,0.5}; + positionBack[] = {0,-0.338,0.5}; + enableZoom = 0; + zoomDuration = 1; + scale = 1; + inBack = 0; + class Areas { + class Dial1 { + selection = "dial1"; + class Controls { + class ButtonDial: GVAR(copperhead_dialButton) { + idc = 111; + tooltip = CSTRING(copperhead_dial_FlightProfile); + }; + }; + }; + class Dial2 { + selection = "dial2"; + class Controls { + class ButtonDial: GVAR(copperhead_dialButton) { + idc = 112; + tooltip = CSTRING(copperhead_dial_GuidanceDelay); + }; + }; + }; + class Dial3 { + selection = "dial3"; + class Controls { + class ButtonDial: GVAR(copperhead_dialButton) { + idc = 113; + tooltip = ECSTRING(laser,laserCode); + }; + }; + }; + class Dial4 { + selection = "dial4"; + class Controls { + class ButtonDial: GVAR(copperhead_dialButton) { + idc = 114; + tooltip = ECSTRING(laser,laserCode); + }; + }; + }; + class Dial5 { + selection = "dial5"; + class Controls { + class ButtonDial: GVAR(copperhead_dialButton) { + idc = 115; + tooltip = ECSTRING(laser,laserCode); + }; + }; + }; + }; + }; + }; +}; diff --git a/addons/missile_clgp/XEH_PREP.hpp b/addons/missile_clgp/XEH_PREP.hpp index c6d509b520a..55264097154 100644 --- a/addons/missile_clgp/XEH_PREP.hpp +++ b/addons/missile_clgp/XEH_PREP.hpp @@ -1,5 +1,12 @@ LOG("prep"); + +PREP(copperhead_attackprofile); +PREP(copperhead_deployCondition); +PREP(copperhead_onfired); +PREP(copperhead_uiCanOpen); +PREP(copperhead_uiCreate); + PREP(submunition_ammoFired); PREP(submunition_applyDrag); PREP(submunition_submunitionCreated); diff --git a/addons/missile_clgp/XEH_postInit.sqf b/addons/missile_clgp/XEH_postInit.sqf index 603af8fcd11..05131b9afca 100644 --- a/addons/missile_clgp/XEH_postInit.sqf +++ b/addons/missile_clgp/XEH_postInit.sqf @@ -1,5 +1,35 @@ #include "script_component.hpp" +GVAR(copperheadMagazines) = createHashMap; + +// Copperhead - Add shell interface action to vehicles that can fire it +if (hasInterface) then { + ["turret", { + params ["_player", "_turret"]; + TRACE_3("turret",_player,_turret,typeOf vehicle _player); + if (_turret isNotEqualTo [0]) exitWith {}; + private _vehicle = vehicle _player; + + if ((!alive _player) || {!alive _vehicle} || {_vehicle getVariable [QGVAR(actionsAdded), false]}) exitWith {}; + _vehicle setVariable [QGVAR(actionsAdded), true]; + + if (((_vehicle weaponsTurret [0]) findIf { + private _compatibleMagazines = compatibleMagazines _x; + (_compatibleMagazines findIf { + private _magazine = _x; + GVAR(copperheadMagazines) getOrDefaultCall [_magazine, { + (getNumber (configFile >> "CfgMagazines" >> _magazine >> QGVAR(copperheadInterface))) == 1 + }, true] + }) != -1 + }) != -1) then { + TRACE_2("adding copperhead action to vehicle",_vehicle,typeOf _vehicle); + private _action = [QGVAR(copperhead), LLSTRING(copperhead_action), "", LINKFUNC(copperhead_uiCreate), LINKFUNC(copperhead_uiCanOpen)] call EFUNC(interact_menu,createAction); + [_vehicle, 1, ["ACE_SelfActions"], _action] call EFUNC(interact_menu,addActionToObject); + }; + }, true] call CBA_fnc_addPlayerEventHandler +}; + + #ifdef ENABLE_QUICK_TESTING call compileScript [QPATHTOF(dev\quickTesting.sqf)]; #endif diff --git a/addons/missile_clgp/data/ace_copperhead_interactive.p3d b/addons/missile_clgp/data/ace_copperhead_interactive.p3d new file mode 100644 index 00000000000..d0bd3236e91 Binary files /dev/null and b/addons/missile_clgp/data/ace_copperhead_interactive.p3d differ diff --git a/addons/missile_clgp/data/copperhead_dial_co.paa b/addons/missile_clgp/data/copperhead_dial_co.paa new file mode 100644 index 00000000000..62e56819f24 Binary files /dev/null and b/addons/missile_clgp/data/copperhead_dial_co.paa differ diff --git a/addons/missile_clgp/data/copperhead_mat.rvmat b/addons/missile_clgp/data/copperhead_mat.rvmat new file mode 100644 index 00000000000..ea44aba3bb6 --- /dev/null +++ b/addons/missile_clgp/data/copperhead_mat.rvmat @@ -0,0 +1,92 @@ +ambient[]={1,0.98500001,0.97000003,1}; +diffuse[]={1,0.98500001,0.97000003,1}; +forcedDiffuse[]={0,0,0,0}; +emmisive[]={0,0,0,1}; +specular[]={0.0001,0.0001,0.0001,0}; +specularPower=2000; +PixelShaderID="Super"; +VertexShaderID="Super"; +class Stage1 +{ + texture="#(argb,8,8,3)color(0.5,0.5,1,1)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage2 +{ + texture = "#(argb,8,8,3)color(0.5,0.5,0.5,1,DT)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {5,-4,0}; + up[] = {8,1.931601,0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage3 +{ + texture = "#(argb,8,8,3)color(0,0,0,0,MC)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage4 +{ + texture="#(argb,8,8,3)color(0,1,1,1)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage5 +{ + texture="#(argb,8,8,3)color(1,1,1,1)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage6 +{ + texture = "#(ai,64,128,1)fresnel(1.5,1.22)"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; +class Stage7 +{ + texture = "a3\data_f\env_land_co.paa"; + uvSource = "tex"; + class uvTransform + { + aside[] = {1.0,0.0,0.0}; + up[] = {0.0,1.0,0.0}; + dir[] = {0.0,0.0,0.0}; + pos[] = {0.0,0.0,0.0}; + }; +}; \ No newline at end of file diff --git a/addons/missile_clgp/data/copperhead_shell_co.paa b/addons/missile_clgp/data/copperhead_shell_co.paa new file mode 100644 index 00000000000..6731f09e1dc Binary files /dev/null and b/addons/missile_clgp/data/copperhead_shell_co.paa differ diff --git a/addons/missile_clgp/data/model.cfg b/addons/missile_clgp/data/model.cfg new file mode 100644 index 00000000000..8d3a9bdb2e8 --- /dev/null +++ b/addons/missile_clgp/data/model.cfg @@ -0,0 +1,66 @@ +class CfgSkeletons { + class Default { + isDiscrete = 1; + skeletonInherit = ""; + skeletonBones[] = {}; + }; + class ace_copperhead_interactive_Skeleton: Default { + isDiscrete = 1; + skeletonInherit = "Default"; + skeletonBones[]={ + "dial1","", + "dial2","", + "dial3","", + "dial4","", + "dial5","" + }; + }; +}; + +class CfgModels { + class Default { + sections[] = {}; + sectionsInherit=""; + skeletonName = ""; + }; + class ace_copperhead_interactive: Default { + sections[]={}; + skeletonName="ace_copperhead_interactive_Skeleton"; + sectionsInherit = "Default"; + class Animations { + class Dial1 { + type="rotation"; + source="Dial1"; // used in ctrlAnimateModel + AnimPeriod = 1; + selection="dial1"; + axis="axis1"; + angle0="rad 7"; + angle1="rad (7 - 7*40)"; + }; + class Dial2: Dial1 { + source="Dial2"; + selection="dial2"; + axis="axis2"; + }; + class Dial3: Dial1 { + source="Dial3"; + selection="dial3"; + axis="axis3"; + }; + class Dial4: Dial1 { + source="Dial4"; + selection="dial4"; + axis="axis4"; + angle0="rad 0"; + angle1="rad (0 + 7*40)"; // lol why is this different + }; + class Dial5: Dial1 { + source="Dial5"; + selection="dial5"; + axis="axis5"; + angle0="rad 0"; + angle1="rad (0 + 7*40)"; + }; + }; + }; +}; diff --git a/addons/missile_clgp/dev/quickTesting.sqf b/addons/missile_clgp/dev/quickTesting.sqf index 0bb998648c2..511ce7a921e 100644 --- a/addons/missile_clgp/dev/quickTesting.sqf +++ b/addons/missile_clgp/dev/quickTesting.sqf @@ -51,16 +51,16 @@ DFUNC(dev_trackShell) = { }; -// ["turret", { -// params ["_player", "_turret"]; -// private _veh = vehicle _player; -// if (currentWeapon _veh == "mortar_155mm_AMOS" && {_veh getVariable [QGVAR(needSetup), true]}) then { -// _veh setVariable [QGVAR(needSetup), false]; -// systemChat "Setting up..."; -// for "_i" from 0 to 9 do { _veh addMagazineTurret ["ace_1rnd_155mm_m712", [0], 1]; }; -// _veh loadMagazine [[0], "mortar_155mm_AMOS", "ace_1rnd_155mm_m712"]; -// }; -// }, true] call CBA_fnc_addPlayerEventHandler; + ["turret", { + params ["_player", "_turret"]; + private _veh = vehicle _player; + if (("ace_1rnd_155mm_m712" in compatibleMagazines ((_veh weaponsTurret [0]) param [0, ""])) && {_veh getVariable [QGVAR(needSetup), true]}) then { + _veh setVariable [QGVAR(needSetup), false]; + systemChat "Setting up..."; + for "_i" from 0 to 9 do { _veh addMagazineTurret ["ace_1rnd_155mm_m712", [0], 1]; }; + _veh loadMagazine [[0], "mortar_155mm_AMOS", "ace_1rnd_155mm_m712"]; + }; + }, true] call CBA_fnc_addPlayerEventHandler; { _x addEventHandler ["Fired", { diff --git a/addons/missile_clgp/functions/fnc_copperhead_attackprofile.sqf b/addons/missile_clgp/functions/fnc_copperhead_attackprofile.sqf new file mode 100644 index 00000000000..b4c4a4b4fbb --- /dev/null +++ b/addons/missile_clgp/functions/fnc_copperhead_attackprofile.sqf @@ -0,0 +1,72 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Copperhead: attack profile + * + * Arguments: + * 0: Seeker Target PosASL + * 1: Guidance Arg Array + * 2: Attack Profile State + * + * Return Value: + * Missile Aim PosASL + * + * Example: + * [[1,2,3], [], []] call ace_missile_clgp_fnc_copperhead_attackProfile + * + * Public: No + */ + +params ["_seekerTargetPos", "_args", "_attackProfileStateParams"]; +_args params ["_firedEH"]; +_firedEH params ["","","","","","","_projectile"]; +_attackProfileStateParams params ["_trajectoryShaped"]; + +// Apply CLGP Drag +// private _dragArray = _projectile getVariable [QGVAR(dragArray), []]; +// if (_dragArray isNotEqualTo []) then { _dragArray call FUNC(submunition_applyDrag) }; + +private _projectilePos = getPosASL _projectile; +private _projectileVelocity = velocity _projectile; +private _projectileElev = acos (_projectileVelocity vectorCos [0,0,-1]); // referenced to straight down + +private _aimASL = []; // return +if (_seekerTargetPos isEqualTo [0,0,0]) then { + private _dir = _projectile getVariable [QGVAR(targetDir), 0]; + private _elev = if (_trajectoryShaped) then { 0 } else { _projectileElev - 90 }; + _aimASL = _projectilePos vectorAdd ([100, _dir, _elev] call CBA_fnc_polar2vect); + if (EGVAR(missileguidance,debug_drawGuidanceInfo)) then { + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0,0,0,1], ASLToAGL _aimASL, + 0.75, 0.75, 0, format ["No TGT: %1 %2", floor _dir, floor _elev], 1, 0.025, "TahomaB"]; + }; + } else { + // have valid seeker target + _aimASL = _seekerTargetPos; + private _dir = (_seekerTargetPos vectorDiff _projectilePos) call CBA_fnc_vectDir; + _projectile setVariable [QGVAR(targetDir), _dir]; + }; + +// Limit max elevation to prevent stalling - unpowered gliding +private _maxElev = 68; // ~2.5 glide ratio (another source says 20-25deg flyout angle) +private _aimDiff = _aimASL vectorDiff _projectilePos; +private _aimElev = acos (_aimDiff vectorCos [0,0,-1]); +private _adjustAngle = _maxElev - _aimElev; +if (_adjustAngle < 0) then { + private _factor = [0.5, 1] select (_aimElev > _projectileElev); + private _adjustOffset = _factor * ((sin _adjustAngle) * vectorMagnitude _aimDiff); + if (EGVAR(missileguidance,debug_drawGuidanceInfo)) then { + drawLine3D [ASLToAGL _aimASL, ASLToAGL (_aimASL vectorAdd [0,0,_adjustOffset]), [0,0.5,1,1]]; + drawIcon3D ["", [0,0.5,1,1], ASLToAGL (_aimASL vectorAdd [0,0,0.5*_adjustOffset]), + 0.75, 0.75, 0, format ["GLIDE LIMIT %1", floor _adjustOffset], 1, 0.025, "TahomaB"]; + }; + _aimASL = _aimASL vectorAdd [0,0,_adjustOffset]; +}; + + +if (EGVAR(missileguidance,debug_drawGuidanceInfo)) then { + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0.2,1,1], ASLToAGL (_projectilePos vectorAdd ((vectorNormalized _projectileVelocity) vectorMultiply 100)), + 0.75, 0.75, 0, format ["V %1", floor _projectileElev], 1, 0.025, "TahomaB"]; +}; + +TRACE_1("dir",_projectilePos getDir _aimASL); +_aimASL diff --git a/addons/missile_clgp/functions/fnc_copperhead_deployCondition.sqf b/addons/missile_clgp/functions/fnc_copperhead_deployCondition.sqf new file mode 100644 index 00000000000..72bdd2cc764 --- /dev/null +++ b/addons/missile_clgp/functions/fnc_copperhead_deployCondition.sqf @@ -0,0 +1,25 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Copperhead: submunition condition, checks if shell should become missile (wings deploy) + * + * Arguments: + * 0: Projectile + * + * Return Value: + * + * + * Example: + * [shell] call ace_missile_clgp_fnc_copperhead_deployCondition + * + * Public: No + */ + +params ["_projectile"]; + +// gyro waits for downward movement +if (((velocity _projectile) select 2) > -2) exitWith { false }; + +// check deploy time +private _deployTime = _projectile getVariable [QGVAR(deployTime), -1]; +CBA_missionTime > _deployTime diff --git a/addons/missile_clgp/functions/fnc_copperhead_onfired.sqf b/addons/missile_clgp/functions/fnc_copperhead_onfired.sqf new file mode 100644 index 00000000000..a384f009d90 --- /dev/null +++ b/addons/missile_clgp/functions/fnc_copperhead_onfired.sqf @@ -0,0 +1,44 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Copperhead: Missile Guidance's On fired - set attack profile settings + * + * Arguments: + * Guidance Args + * + * Return Value: + * None + * + * Example: + * [] call ace_missile_clgp_fnc_copperhead_onfired + * + * Public: No + */ + +params ["_firedEH", "_launchParams", "", "", "_stateParams"]; +_launchParams params ["","","","","","_laserInfo"]; +_firedEH params ["_shooter","","","","","","_projectile"]; +_stateParams params ["", "", "_attackProfileStateParams"]; + +(_shooter getVariable [QGVAR(copperhead_settings), COPPERHEAD_DEFUALT_SETTINGS]) + params [["_trajectorySetting", 1], ["_delaySetting", 1], ["_laserCodeA", 1], ["_laserCodeB", 1], ["_laserCodeC", 1]]; +TRACE_6("copperhead_onfired",_projectile,_trajectorySetting,_delaySetting,_laserCodeA,_laserCodeB,_laserCodeC); + +// Set trajectory from first dial + +// Changing path without active feedback causes problems on current missile guidance +// probably due to poor vector change in ace_missileguidance_fnc_guidancePFH, disable for now +private _trajectoryShaped = _trajectorySetting >= 3; // 1-2 is ballistic, 3-8 is shaped +_attackProfileStateParams set [0, _trajectoryShaped]; + +// set var for submuntion's deployCondition from second dial +private _delayDeployment = linearConversion [1, 8, _delaySetting, 1, [45, 48] select _trajectoryShaped, true]; +_projectile setVariable [QGVAR(deployTime), _delayDeployment + CBA_missionTime]; + +// Set laser guidance info from last 3 dials +// Note: copperhead uses a 3 digit code - techinally 111 should be able to lock onto any X111 4 digit code +// not sure if worth modifying ace_laser for this, for now just assume high digit is 1 +private _laserCode = 1000 + 100 * _laserCodeA + 10 * _laserCodeB + _laserCodeC; +_laserInfo set [0, _laserCode]; + +TRACE_3("",_trajectoryShaped,_delayDeployment,_laserCode); diff --git a/addons/missile_clgp/functions/fnc_copperhead_uiCanOpen.sqf b/addons/missile_clgp/functions/fnc_copperhead_uiCanOpen.sqf new file mode 100644 index 00000000000..05e027c02c5 --- /dev/null +++ b/addons/missile_clgp/functions/fnc_copperhead_uiCanOpen.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Condition for showing copperhead interface, used in both interaction menu and inside dialog loop + * + * Arguments: + * Args + * + * Return Value: + * None + * + * Example: + * [vehicle, player] call ace_missile_clgp_fnc_copperhead_uiCanOpen + * + * Public: No + */ + +params ["_vehicle", "_player"]; +// TRACE_2("copperhead_uiCanOpen",_vehicle,_player); + +(_player in _vehicle) +&& {(_vehicle unitTurret _player) isEqualTo [0]} +&& {alive _vehicle} +&& { + ((magazinesAllTurrets _vehicle) findIf { + _x params ["_xMag", "_xTurret", "_xAmmo"]; + (_xTurret isEqualTo [0]) && {_xAmmo > 0} && {GVAR(copperheadMagazines) getOrDefault [_xMag, false]} + }) != -1 +} diff --git a/addons/missile_clgp/functions/fnc_copperhead_uiCreate.sqf b/addons/missile_clgp/functions/fnc_copperhead_uiCreate.sqf new file mode 100644 index 00000000000..8eaf7e6fff6 --- /dev/null +++ b/addons/missile_clgp/functions/fnc_copperhead_uiCreate.sqf @@ -0,0 +1,87 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Shows copperhead dialog + * + * Arguments: + * Args + * + * Return Value: + * None + * + * Example: + * [vehicle, player] call ace_missile_clgp_fnc_copperhead_uiCreate + * + * Public: No + */ + +[{ // execNextFrame to prevent issues with interaction menu closing + + params ["_vehicle", "_player"]; + TRACE_2("copperhead_uiCreate",_vehicle,_player); + + createDialog QGVAR(copperhead_dialog); + + private _display = uiNamespace getVariable [QGVAR(copperhead_dialog), displayNull]; + if (isNull _display) exitWith { ERROR("bad dialog");}; + + private _copperheadSettings = _vehicle getVariable [QGVAR(copperhead_settings), COPPERHEAD_DEFUALT_SETTINGS]; + TRACE_1("current",_copperheadSettings); + _display setVariable ["vehicle", _vehicle]; + _display setVariable ["settings", _copperheadSettings]; + + + // Scale and center model + private _scale = 1 / (getResolution # 5); // keep object the same size for any interface size + private _base = ["3d", [0,-0.338, 0.3333], _scale] call EFUNC(common,rscObjectHelper); + (_display displayCtrl 100) ctrlSetPosition _base; + (_display displayCtrl 100) ctrlSetModelScale _scale; + + + // Handle mouse clicks on the dials + private _fnc_dialClick = { + params ["_control", "_button", "_xPos", "_yPos", "_shift", "_ctrl", "_alt"]; + private _display = ctrlParent _control; + private _settings = _display getVariable "settings"; + + private _add = if (_button == 0) then { 1 } else { -1 }; + + private _dialIndex = ((ctrlIDC _control) % 10) - 1; + private _newValue = ((_add + _settings # _dialIndex) max 1) min 8; + _settings set [_dialIndex, _newValue]; + }; + { + (_display displayCtrl _x) ctrlAddEventHandler ["MouseButtonUp", _fnc_dialClick]; + } forEach [111, 112, 113, 114, 115]; + + + // Update display each frame + private _fnc_eachFrame = { + params ["_display"]; + private _vehicle = _display getVariable "vehicle"; + private _settings = _display getVariable "settings"; + + if (!([_vehicle, ace_player] call FUNC(copperhead_uiCanOpen))) exitWith { + closeDialog 5; + }; + { + private _animName = format ["Dial%1", _forEachIndex + 1]; + private _phase = linearConversion [1,8,_x,0,1]; // ~40deg per click, handled by model.cfg + (_display displayCtrl 100) ctrlAnimateModel [_animName, _phase]; + } forEach _settings; + }; + _display displayAddEventHandler ["MouseMoving", _fnc_eachFrame]; + _display displayAddEventHandler ["MouseHolding", _fnc_eachFrame]; + + + // Save data to vehicle on close + _display displayAddEventHandler ["Unload", { + params ["_display", "_exitCode"]; + private _vehicle = _display getVariable "vehicle"; + private _settings = _display getVariable "settings"; + TRACE_3("Unload",_exitCode,_vehicle,_settings); + if ((!alive _vehicle) || {_settings isEqualTo []}) exitWith { ERROR_2("unloaded with bad input %1-%2",_vehicle,_settings); }; + + _vehicle setVariable [QGVAR(copperhead_settings), _settings, true]; // global + }]; +}, _this] call CBA_fnc_execNextFrame; diff --git a/addons/missile_clgp/functions/fnc_submunition_applyDrag.sqf b/addons/missile_clgp/functions/fnc_submunition_applyDrag.sqf index b0f6b3303cd..359d6edfb23 100644 --- a/addons/missile_clgp/functions/fnc_submunition_applyDrag.sqf +++ b/addons/missile_clgp/functions/fnc_submunition_applyDrag.sqf @@ -19,11 +19,11 @@ params ["_projectile", "_kFactor", "_time"]; -private _bulletVelocity = velocity _projectile; private _deltaT = CBA_missionTime - _time; _this set [2, CBA_missionTime]; if (_kFactor != 0) then { + private _bulletVelocity = velocity _projectile; private _trueVelocity = _bulletVelocity vectorDiff wind; private _trueSpeed = vectorMagnitude _trueVelocity; @@ -34,6 +34,3 @@ if (_kFactor != 0) then { _projectile setVelocity _bulletVelocity; }; -private _dir = vectorNormalized _bulletVelocity; -_projectile setVectorDirAndUp [_dir, _dir vectorCrossProduct vectorSide _projectile]; -TRACE_2("setVectorDirAndUp",_projectile,_dir); diff --git a/addons/missile_clgp/functions/fnc_submunition_submunitionCreated.sqf b/addons/missile_clgp/functions/fnc_submunition_submunitionCreated.sqf index 8c1be94a802..989f53b7fb2 100644 --- a/addons/missile_clgp/functions/fnc_submunition_submunitionCreated.sqf +++ b/addons/missile_clgp/functions/fnc_submunition_submunitionCreated.sqf @@ -6,28 +6,36 @@ * Arguments: * 0: Old Projectile * 1: New Projectile + * 2: PositionASL + * 3: Velocity * * Return Value: * Nothing * * Example: - * [a,b] call ace_missile_clgp_fnc_submunition_submunitionCreated + * [a, b, [], [1,0,-1]] call ace_missile_clgp_fnc_submunition_submunitionCreated * * Public: No */ -params ["_projectile", "_submunitionProjectile"]; +params ["_projectile", "_submunitionProjectile", "", "_velocity"]; private _guidanceArgs = _projectile getVariable [QGVAR(guidanceArgs), []]; TRACE_2("submunitionCreated",typeOf _projectile,typeOf _submunitionProjectile); if (isNull _submunitionProjectile) exitWith { WARNING_1("null %1",_this); }; +(_velocity call CBA_fnc_vect2Polar) params ["", "_currentDir", "_currentElev"]; +_submunitionProjectile setVariable [QGVAR(targetDir), _currentDir]; + if (_guidanceArgs isNotEqualTo []) then { // Inject the submunition projectile and time into guidance args _guidanceArgs params ["_firedEH", "", "", "", "_stateParams"]; - _firedEH set [6, _submunitionProjectile]; // _firedEH params ["","","","","","","_projectile"]; - _stateParams set [0, diag_tickTime]; // _stateParams params ["_lastRunTime"] + // _firedEH params ["","","","","","","_projectile"]; + _firedEH set [6, _submunitionProjectile]; + // _stateParams params ["_lastRunTime", "", "", "", "", "_guidanceParameters"]; + _stateParams set [0, diag_tickTime]; + _stateParams set [5, [_currentDir, 0, _currentElev]]; TRACE_2("-Starting missileGuidance",_submunitionProjectile,count _guidanceArgs); - [EFUNC(missileguidance,guidancePFH), 0, _guidanceArgs] call CBA_fnc_addPerFrameHandler; + [{call EFUNC(missileguidance,guidancePFH)}, 0, _guidanceArgs] call CBA_fnc_addPerFrameHandler; }; private _deployArtilleryDragConfig = (configOf _projectile) >> QGVAR(artilleryDrag); @@ -36,7 +44,7 @@ if (isNumber _deployArtilleryDragConfig) then { if (_deployArtilleryDrag < 0) exitWith { TRACE_1("-Ignoring Drag",_deployArtilleryDrag); }; private _kFactor = _projectile getVariable [QEGVAR(artillerytables,kFactor), 0]; TRACE_2("-Drag",_deployArtilleryDrag,_kFactor); - _kFactor = _kFactor * _deployArtilleryDrag; // Can be 0 from either source (0 is valid and will keep nose pointed) + _kFactor = _kFactor * _deployArtilleryDrag; // Can be 0 from either source (0 is valid) private _dragArray = [_submunitionProjectile, _kFactor, CBA_missionTime]; _submunitionProjectile setVariable [QGVAR(dragArray), _dragArray]; }; diff --git a/addons/missile_clgp/script_component.hpp b/addons/missile_clgp/script_component.hpp index 2d2043b2a12..025b65dac85 100644 --- a/addons/missile_clgp/script_component.hpp +++ b/addons/missile_clgp/script_component.hpp @@ -1,5 +1,5 @@ #define COMPONENT missile_clgp -#define COMPONENT_BEAUTIFIED Cannon Launched Guided Projectiles +#define COMPONENT_BEAUTIFIED Cannon-Launched Guided Projectiles #include "\z\ace\addons\main\script_mod.hpp" // #define DEBUG_MODE_FULL diff --git a/addons/missile_clgp/stringtable.xml b/addons/missile_clgp/stringtable.xml index 22aaf28a2a2..1955ceb3198 100644 --- a/addons/missile_clgp/stringtable.xml +++ b/addons/missile_clgp/stringtable.xml @@ -1,6 +1,15 @@ + + Configure M712 Shell + + + Flight Profile + + + Guidance Delay + Semi-Active Laser Guided 40mm Grenade Grenade semi-active à guidage laser de 40 mm