diff --git a/.hemtt/launch.toml b/.hemtt/launch.toml index ff6bdadd3b9..02fe625a215 100644 --- a/.hemtt/launch.toml +++ b/.hemtt/launch.toml @@ -3,6 +3,18 @@ workshop = [ "450814997", # CBA_A3 ] +[zen] +extends = "default" +workshop = [ + "1779063631", # Zeus Enhanced +] + +[adt] +extends = "default" +workshop = [ + "3499977893", # ADT +] + [rhs] extends = "default" workshop = [ @@ -26,11 +38,14 @@ workshop = [ "1369691841", # Community Factions Project ] -[wardrobe] +[missile_defense] extends = "default" +mission = "missileDefense.Stratis" + +[wardrobe] +extends = "adt" mission = "Wardrobe.VR" workshop = [ - "3499977893", # Advanced Developer Tools "1779063631", # ZEN # "751965892", # ACRE # "623475643", # eden enhanced diff --git a/.hemtt/missions/missileDefense.Stratis/initServer.sqf b/.hemtt/missions/missileDefense.Stratis/initServer.sqf new file mode 100644 index 00000000000..491d9d5cbcc --- /dev/null +++ b/.hemtt/missions/missileDefense.Stratis/initServer.sqf @@ -0,0 +1,10 @@ +/// Create a system that engages independent side projectiles. +private _defense = [[independent]] call ace_missile_defense_fnc_createSystem; + +[_defense, w_tracker_1] call ace_missile_defense_fnc_registerTracker; +[_defense, w_tracker_2] call ace_missile_defense_fnc_registerTracker; + +[_defense, w_launcher_1] call ace_missile_defense_fnc_registerLauncher; +[_defense, w_launcher_2] call ace_missile_defense_fnc_registerLauncher; +[_defense, w_launcher_3] call ace_missile_defense_fnc_registerLauncher; +[_defense, w_launcher_4] call ace_missile_defense_fnc_registerLauncher; diff --git a/.hemtt/missions/missileDefense.Stratis/mission.sqm b/.hemtt/missions/missileDefense.Stratis/mission.sqm new file mode 100644 index 00000000000..d5831b9b8e1 --- /dev/null +++ b/.hemtt/missions/missileDefense.Stratis/mission.sqm @@ -0,0 +1,1472 @@ +version=54; +class EditorData +{ + moveGridStep=1; + angleGridStep=0.2617994; + scaleGridStep=1; + autoGroupingDist=10; + toggles=1; + class ItemIDProvider + { + nextID=71; + }; + class Camera + { + pos[]={3938.1497,121.18645,6352.4463}; + dir[]={-0.48247248,-0.29674312,-0.82411397}; + up[]={-0.14992332,0.95495731,-0.25608489}; + aside[]={-0.86298507,7.4505806e-09,0.50522935}; + }; +}; +binarizationWanted=0; +sourceName="missiledefense"; +addons[]= +{ + "A3_Characters_F_Common", + "A3_Static_F_Sams_Radar_System_01", + "A3_Static_F_Jets_SAM_System_01", + "A3_Soft_F_Gamma_Truck_02", + "ace_realisticnames", + "A3_Characters_F", + "A3_Static_F_Mortar_01", + "A3_Characters_F_AoW", + "A3_Armor_F_Gamma_MBT_02" +}; +class AddonsMetaData +{ + class List + { + items=7; + class Item0 + { + className="A3_Characters_F"; + name="Arma 3 Alpha - Characters and Clothing"; + author="Bohemia Interactive"; + url="https://www.arma3.com"; + }; + class Item1 + { + className="A3_Static_F_Sams"; + name="Arma 3 Sams - Turrets"; + author="Bohemia Interactive"; + url="https://www.arma3.com"; + }; + class Item2 + { + className="A3_Static_F_Jets"; + name="Arma 3 Jets - Turrets"; + author="Bohemia Interactive"; + url="https://www.arma3.com"; + }; + class Item3 + { + className="A3_Soft_F_Gamma"; + name="Arma 3 - Unarmored Land Vehicles"; + author="Bohemia Interactive"; + url="https://www.arma3.com"; + }; + class Item4 + { + className="A3_Static_F"; + name="Arma 3 Alpha - Turrets"; + author="Bohemia Interactive"; + url="https://www.arma3.com"; + }; + class Item5 + { + className="A3_Characters_F_AoW"; + name="Arma 3 Art of War - Characters and Clothing"; + author="Bohemia Interactive"; + url="https://www.arma3.com"; + }; + class Item6 + { + className="A3_Armor_F_Gamma"; + name="Arma 3 - Armored Land Vehicles"; + author="Bohemia Interactive"; + url="https://www.arma3.com"; + }; + }; +}; +dlcs[]= +{ + "Jets", + "AoW" +}; +randomSeed=4977539; +class ScenarioData +{ + author="Brett"; +}; +class Mission +{ + class Intel + { + timeOfChanges=1800.0002; + startWeather=0.30000001; + startWind=0.1; + startWaves=0.1; + forecastWeather=0.30000001; + forecastWind=0.1; + forecastWaves=0.1; + forecastLightnings=0.1; + wavesForced=1; + windForced=1; + year=2035; + month=7; + day=6; + hour=12; + minute=0; + startFogDecay=0.014; + forecastFogDecay=0.014; + }; + class Entities + { + items=28; + class Item0 + { + dataType="Group"; + side="West"; + class Entities + { + items=1; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={1841.5955,8.430357,5753.5996}; + angles[]={0,2.2108259,0}; + }; + side="West"; + flags=2; + class Attributes + { + name="w_tracker_1G"; + }; + id=2; + type="B_UAV_AI"; + atlOffset=2.9289188; + }; + }; + class Attributes + { + }; + class CrewLinks + { + class LinkIDProvider + { + nextID=1; + }; + class Links + { + items=1; + class Item0 + { + linkID=0; + item0=2; + item1=1; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + }; + }; + id=0; + atlOffset=4.7683716e-07; + }; + class Item1 + { + dataType="Object"; + class PositionInfo + { + position[]={1841.595,8.4289188,5753.5498}; + angles[]={0,2.2108259,0}; + }; + side="West"; + flags=6; + class Attributes + { + name="w_tracker_1"; + reportRemoteTargets=1; + receiveRemoteTargets=1; + reportOwnPosition=1; + aiRadarUsage=1; + }; + id=1; + type="B_Radar_System_01_F"; + atlOffset=4.7683716e-07; + }; + class Item2 + { + dataType="Group"; + side="West"; + class Entities + { + items=1; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={1634.5385,8.430357,5396.5015}; + angles[]={0,2.2108259,0}; + }; + side="West"; + flags=2; + class Attributes + { + name="w_tracker_1G_1"; + }; + id=4; + type="B_UAV_AI"; + atlOffset=2.9289188; + }; + }; + class Attributes + { + }; + class CrewLinks + { + class LinkIDProvider + { + nextID=1; + }; + class Links + { + items=1; + class Item0 + { + linkID=0; + item0=4; + item1=5; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + }; + }; + id=3; + atlOffset=4.7683716e-07; + }; + class Item3 + { + dataType="Object"; + class PositionInfo + { + position[]={1672.0404,8.4289188,5380.5679}; + angles[]={0,2.2108259,0}; + }; + side="West"; + flags=6; + class Attributes + { + name="w_tracker_2"; + reportRemoteTargets=1; + receiveRemoteTargets=1; + reportOwnPosition=1; + aiRadarUsage=1; + }; + id=5; + type="B_Radar_System_01_F"; + atlOffset=4.7683716e-07; + }; + class Item4 + { + dataType="Group"; + side="West"; + class Entities + { + items=1; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={1865.6261,7.3601575,5768.5386}; + angles[]={0,2.125968,0.0075049158}; + }; + side="West"; + flags=2; + class Attributes + { + name="w_launcher_1G"; + }; + id=8; + type="B_UAV_AI"; + atlOffset=1.7565231; + }; + }; + class Attributes + { + }; + class CrewLinks + { + class LinkIDProvider + { + nextID=1; + }; + class Links + { + items=1; + class Item0 + { + linkID=0; + item0=8; + item1=7; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + }; + }; + id=6; + atlOffset=-4.7683716e-07; + }; + class Item5 + { + dataType="Object"; + class PositionInfo + { + position[]={1860.7798,7.3223705,5771.8071}; + angles[]={0,2.125968,0.0075049158}; + }; + side="West"; + flags=6; + class Attributes + { + name="w_launcher_1"; + reportRemoteTargets=1; + receiveRemoteTargets=1; + reportOwnPosition=1; + aiRadarUsage=1; + }; + id=7; + type="B_SAM_System_01_F"; + atlOffset=-4.7683716e-07; + }; + class Item6 + { + dataType="Group"; + side="West"; + class Entities + { + items=1; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={1853.2793,7.2942109,5573.5566}; + angles[]={0,2.125968,0}; + }; + side="West"; + flags=2; + class Attributes + { + name="w_launcher_1G_1"; + }; + id=10; + type="B_UAV_AI"; + atlOffset=1.7927723; + }; + }; + class Attributes + { + }; + class CrewLinks + { + class LinkIDProvider + { + nextID=1; + }; + class Links + { + items=1; + class Item0 + { + linkID=0; + item0=10; + item1=11; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + }; + }; + id=9; + atlOffset=-4.7683716e-07; + }; + class Item7 + { + dataType="Object"; + class PositionInfo + { + position[]={1848.433,7.2564731,5576.8252}; + angles[]={0,2.125968,0}; + }; + side="West"; + flags=6; + class Attributes + { + name="w_launcher_2"; + reportRemoteTargets=1; + receiveRemoteTargets=1; + reportOwnPosition=1; + aiRadarUsage=1; + }; + id=11; + type="B_SAM_System_01_F"; + atlOffset=-4.7683716e-07; + }; + class Item8 + { + dataType="Group"; + side="West"; + class Entities + { + items=1; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={1999.2325,7.4942107,5724.9116}; + angles[]={6.2815661,2.125968,6.2820406}; + }; + side="West"; + flags=2; + class Attributes + { + name="w_launcher_1G_2"; + }; + id=13; + type="B_UAV_AI"; + atlOffset=1.7927723; + }; + }; + class Attributes + { + }; + class CrewLinks + { + class LinkIDProvider + { + nextID=1; + }; + class Links + { + items=1; + class Item0 + { + linkID=0; + item0=13; + item1=14; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + }; + }; + id=12; + atlOffset=0.080667496; + }; + class Item9 + { + dataType="Object"; + class PositionInfo + { + position[]={2131.7688,5.7456942,5854.6729}; + angles[]={6.2815661,2.125968,6.2820406}; + }; + side="West"; + flags=6; + class Attributes + { + name="w_launcher_3"; + reportRemoteTargets=1; + receiveRemoteTargets=1; + reportOwnPosition=1; + aiRadarUsage=1; + }; + id=14; + type="B_SAM_System_01_F"; + atlOffset=0.080667496; + }; + class Item10 + { + dataType="Group"; + side="West"; + class Entities + { + items=1; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={2005.0648,4.7820444,5320.2202}; + angles[]={0,2.125968,0.012496647}; + }; + side="West"; + flags=2; + class Attributes + { + name="w_launcher_1G_3"; + }; + id=16; + type="B_UAV_AI"; + atlOffset=1.7961347; + }; + }; + class Attributes + { + }; + class CrewLinks + { + class LinkIDProvider + { + nextID=1; + }; + class Links + { + items=1; + class Item0 + { + linkID=0; + item0=16; + item1=17; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + }; + }; + id=15; + atlOffset=-0.00018239021; + }; + class Item11 + { + dataType="Object"; + class PositionInfo + { + position[]={2002.6296,4.7092991,5330.0762}; + angles[]={0,2.125968,0.012496647}; + }; + side="West"; + flags=6; + class Attributes + { + name="w_launcher_4"; + reportRemoteTargets=1; + receiveRemoteTargets=1; + reportOwnPosition=1; + aiRadarUsage=1; + }; + id=17; + type="B_SAM_System_01_F"; + atlOffset=-0.00018239021; + }; + class Item12 + { + dataType="Object"; + class PositionInfo + { + position[]={6348.5483,9.9967537,5395.127}; + angles[]={0.079831354,5.3393812,0.029984757}; + }; + side="Independent"; + flags=4; + class Attributes + { + fuel=0; + name="i_launcher_1"; + }; + id=19; + type="I_Truck_02_MRL_F"; + atlOffset=-0.011143208; + }; + class Item13 + { + dataType="Group"; + side="Independent"; + class Entities + { + items=6; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={4370.0044,226.53734,3808.5708}; + angles[]={0.039985489,5.3393812,0.042481314}; + }; + side="Independent"; + flags=4; + class Attributes + { + name="i_launcher_3D"; + }; + id=23; + type="I_soldier_F"; + atlOffset=-0.057830811; + }; + class Item1 + { + dataType="Object"; + class PositionInfo + { + position[]={4370.0044,229.18925,3808.5576}; + angles[]={0.039985489,5.3393812,0.042481314}; + }; + side="Independent"; + flags=2; + class Attributes + { + name="i_launcher_3G"; + }; + id=24; + type="I_soldier_F"; + atlOffset=2.5948029; + }; + class Item2 + { + dataType="Object"; + class PositionInfo + { + position[]={4368.9648,224.92839,3763.4426}; + angles[]={0.079831354,5.3393812,0.029984757}; + }; + side="Independent"; + flags=4; + class Attributes + { + name="i_launcher_1D"; + }; + id=20; + type="I_soldier_F"; + }; + class Item3 + { + dataType="Object"; + class PositionInfo + { + position[]={4368.9648,227.58031,3763.4294}; + angles[]={0.079831354,5.3393812,0.029984757}; + }; + side="Independent"; + class Attributes + { + name="i_launcher_1G"; + }; + id=21; + type="I_soldier_F"; + atlOffset=2.6519775; + class CustomAttributes + { + class Attribute0 + { + property="speaker"; + expression="_this setspeaker _value;"; + class Value + { + class data + { + singleType="STRING"; + value="Male04GRE"; + }; + }; + }; + class Attribute1 + { + property="pitch"; + expression="_this setpitch _value;"; + class Value + { + class data + { + singleType="SCALAR"; + value=0.99000001; + }; + }; + }; + nAttributes=2; + }; + }; + class Item4 + { + dataType="Object"; + class PositionInfo + { + position[]={4359.6445,225.93385,3791.9194}; + angles[]={0.079831354,5.3393812,0.044977132}; + }; + side="Independent"; + flags=4; + class Attributes + { + name="i_launcher_2D"; + }; + id=27; + type="I_soldier_F"; + atlOffset=-0.13253784; + }; + class Item5 + { + dataType="Object"; + class PositionInfo + { + position[]={4359.6445,228.58577,3791.9063}; + angles[]={0.079831354,5.3393812,0.044977132}; + }; + side="Independent"; + class Attributes + { + name="i_launcher_2G"; + }; + id=28; + type="I_soldier_F"; + atlOffset=2.5202637; + }; + }; + class Attributes + { + }; + class CrewLinks + { + class LinkIDProvider + { + nextID=6; + }; + class Links + { + items=6; + class Item0 + { + linkID=0; + item0=23; + item1=25; + class CustomData + { + role=1; + }; + }; + class Item1 + { + linkID=1; + item0=24; + item1=25; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + class Item2 + { + linkID=2; + item0=20; + item1=19; + class CustomData + { + role=1; + }; + }; + class Item3 + { + linkID=3; + item0=21; + item1=19; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + class Item4 + { + linkID=4; + item0=27; + item1=29; + class CustomData + { + role=1; + }; + }; + class Item5 + { + linkID=5; + item0=28; + item1=29; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + }; + }; + id=22; + atlOffset=-0.010426044; + }; + class Item14 + { + dataType="Object"; + class PositionInfo + { + position[]={6352.0654,5.6805224,5456.207}; + angles[]={0.039985489,5.3393812,0.042481314}; + }; + side="Independent"; + flags=6; + class Attributes + { + fuel=0; + name="i_launcher_3"; + }; + id=25; + type="I_Truck_02_MRL_F"; + atlOffset=-0.010426044; + }; + class Item15 + { + dataType="Object"; + class PositionInfo + { + position[]={6340.3115,7.9278345,5424.2412}; + angles[]={0.079831354,5.3393812,0.044977132}; + }; + side="Independent"; + flags=4; + class Attributes + { + fuel=0; + name="i_launcher_2"; + }; + id=29; + type="I_Truck_02_MRL_F"; + atlOffset=-0.02998209; + }; + class Item16 + { + dataType="Group"; + side="West"; + class Entities + { + items=1; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={3934.6416,116.58717,6344.4492}; + angles[]={0,2.1423652,0}; + }; + side="West"; + flags=7; + class Attributes + { + isPlayer=1; + }; + id=31; + type="B_Competitor_F"; + }; + }; + class Attributes + { + }; + id=30; + }; + class Item17 + { + dataType="Group"; + side="Independent"; + class Entities + { + items=5; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={4084.835,221.95305,4596.6738}; + }; + side="Independent"; + flags=2; + class Attributes + { + }; + id=43; + type="I_soldier_F"; + atlOffset=0.72161865; + }; + class Item1 + { + dataType="Object"; + class PositionInfo + { + position[]={4090.7632,221.95305,4603.2163}; + }; + side="Independent"; + class Attributes + { + }; + id=45; + type="I_soldier_F"; + atlOffset=0.72161865; + }; + class Item2 + { + dataType="Object"; + class PositionInfo + { + position[]={4092.0813,221.95305,4598.0586}; + }; + side="Independent"; + class Attributes + { + }; + id=47; + type="I_soldier_F"; + atlOffset=0.72161865; + }; + class Item3 + { + dataType="Object"; + class PositionInfo + { + position[]={4088.9336,221.9039,4594.4902}; + angles[]={6.22824,0,0.037485532}; + }; + side="Independent"; + class Attributes + { + }; + id=49; + type="I_soldier_F"; + atlOffset=0.72322083; + }; + class Item4 + { + dataType="Object"; + class PositionInfo + { + position[]={4097.4507,221.95305,4596.8687}; + }; + side="Independent"; + class Attributes + { + }; + id=51; + type="I_soldier_F"; + atlOffset=0.72161865; + }; + }; + class Attributes + { + }; + class CrewLinks + { + class LinkIDProvider + { + nextID=5; + }; + class Links + { + items=5; + class Item0 + { + linkID=0; + item0=43; + item1=42; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + class Item1 + { + linkID=1; + item0=45; + item1=44; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + class Item2 + { + linkID=2; + item0=47; + item1=46; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + class Item3 + { + linkID=3; + item0=49; + item1=48; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + class Item4 + { + linkID=4; + item0=51; + item1=50; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + }; + }; + id=41; + }; + class Item18 + { + dataType="Object"; + class PositionInfo + { + position[]={4084.835,221.95161,4596.624}; + }; + side="Independent"; + flags=6; + class Attributes + { + }; + id=42; + type="I_Mortar_01_F"; + }; + class Item19 + { + dataType="Object"; + class PositionInfo + { + position[]={4090.7632,221.95161,4603.1665}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=44; + type="I_Mortar_01_F"; + }; + class Item20 + { + dataType="Object"; + class PositionInfo + { + position[]={4092.0813,221.95161,4598.0088}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=46; + type="I_Mortar_01_F"; + }; + class Item21 + { + dataType="Object"; + class PositionInfo + { + position[]={4088.9336,221.90247,4594.4404}; + angles[]={6.22824,0,0.037485532}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=48; + type="I_Mortar_01_F"; + }; + class Item22 + { + dataType="Object"; + class PositionInfo + { + position[]={4097.4507,221.95161,4596.8188}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=50; + type="I_Mortar_01_F"; + }; + class Item23 + { + dataType="Group"; + side="West"; + class Entities + { + items=1; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={1908.0338,18.457346,5716.3872}; + angles[]={0,0.35642493,0}; + }; + side="West"; + flags=7; + class Attributes + { + }; + id=53; + type="B_Officer_Parade_F"; + }; + }; + class Attributes + { + }; + id=52; + }; + class Item24 + { + dataType="Object"; + class PositionInfo + { + position[]={6427.9336,10.260787,5430.6284}; + angles[]={0.0099949092,0,6.2756844}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=55; + type="O_MBT_02_arty_F"; + atlOffset=4.2915344e-06; + }; + class Item25 + { + dataType="Object"; + class PositionInfo + { + position[]={6413.8921,10.358639,5425.2012}; + angles[]={0.0075011365,0,6.2731905}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=60; + type="O_MBT_02_arty_F"; + }; + class Item26 + { + dataType="Object"; + class PositionInfo + { + position[]={6421.1738,10.497168,5415.5518}; + angles[]={0.019996032,0,6.2756844}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=65; + type="O_MBT_02_arty_F"; + atlOffset=6.1988831e-06; + }; + class Item27 + { + dataType="Group"; + side="Independent"; + class Entities + { + items=9; + class Item0 + { + dataType="Object"; + class PositionInfo + { + position[]={6427.9116,7.3461146,5430.6489}; + angles[]={0.0099949092,0,6.2756844}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=56; + type="O_crew_F"; + atlOffset=3.8146973e-06; + }; + class Item1 + { + dataType="Object"; + class PositionInfo + { + position[]={6427.9336,10.262226,5430.6782}; + angles[]={0.0099949092,0,6.2756844}; + }; + side="Independent"; + flags=2; + class Attributes + { + }; + id=57; + type="O_crew_F"; + atlOffset=2.9165735; + }; + class Item2 + { + dataType="Object"; + class PositionInfo + { + position[]={6427.9336,10.262226,5430.6782}; + angles[]={0.0099949092,0,6.2756844}; + }; + side="Independent"; + class Attributes + { + }; + id=58; + type="O_crew_F"; + atlOffset=2.9165735; + }; + class Item3 + { + dataType="Object"; + class PositionInfo + { + position[]={6413.8628,7.4439664,5425.229}; + angles[]={0.0075011365,0,6.2731905}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=61; + type="O_crew_F"; + }; + class Item4 + { + dataType="Object"; + class PositionInfo + { + position[]={6413.8921,10.360077,5425.251}; + angles[]={0.0075011365,0,6.2731905}; + }; + side="Independent"; + class Attributes + { + }; + id=62; + type="O_crew_F"; + atlOffset=2.9165688; + }; + class Item5 + { + dataType="Object"; + class PositionInfo + { + position[]={6413.8921,10.360077,5425.251}; + angles[]={0.0075011365,0,6.2731905}; + }; + side="Independent"; + class Attributes + { + }; + id=63; + type="O_crew_F"; + atlOffset=2.9165688; + }; + class Item6 + { + dataType="Object"; + class PositionInfo + { + position[]={6421.1519,7.5829329,5415.5435}; + angles[]={0.019996032,0,6.2756844}; + }; + side="Independent"; + flags=4; + class Attributes + { + }; + id=66; + type="O_crew_F"; + atlOffset=5.7220459e-06; + }; + class Item7 + { + dataType="Object"; + class PositionInfo + { + position[]={6421.1738,10.498606,5415.6016}; + angles[]={0.019996032,0,6.2756844}; + }; + side="Independent"; + class Attributes + { + }; + id=67; + type="O_crew_F"; + atlOffset=2.9170065; + }; + class Item8 + { + dataType="Object"; + class PositionInfo + { + position[]={6421.1738,10.498606,5415.6016}; + angles[]={0.019996032,0,6.2756844}; + }; + side="Independent"; + class Attributes + { + }; + id=68; + type="O_crew_F"; + atlOffset=2.9170065; + }; + }; + class Attributes + { + }; + class CrewLinks + { + class LinkIDProvider + { + nextID=9; + }; + class Links + { + items=9; + class Item0 + { + linkID=0; + item0=56; + item1=55; + class CustomData + { + role=1; + }; + }; + class Item1 + { + linkID=1; + item0=57; + item1=55; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + class Item2 + { + linkID=2; + item0=58; + item1=55; + class CustomData + { + role=2; + turretPath[]={0,0}; + }; + }; + class Item3 + { + linkID=3; + item0=61; + item1=60; + class CustomData + { + role=1; + }; + }; + class Item4 + { + linkID=4; + item0=62; + item1=60; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + class Item5 + { + linkID=5; + item0=63; + item1=60; + class CustomData + { + role=2; + turretPath[]={0,0}; + }; + }; + class Item6 + { + linkID=6; + item0=66; + item1=65; + class CustomData + { + role=1; + }; + }; + class Item7 + { + linkID=7; + item0=67; + item1=65; + class CustomData + { + role=2; + turretPath[]={0}; + }; + }; + class Item8 + { + linkID=8; + item0=68; + item1=65; + class CustomData + { + role=2; + turretPath[]={0,0}; + }; + }; + }; + }; + id=69; + atlOffset=4.2915344e-06; + }; + }; +}; diff --git a/addons/missile_defense/$PBOPREFIX$ b/addons/missile_defense/$PBOPREFIX$ new file mode 100644 index 00000000000..5803d666c6e --- /dev/null +++ b/addons/missile_defense/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\missile_defense diff --git a/addons/missile_defense/CfgEventHandlers.hpp b/addons/missile_defense/CfgEventHandlers.hpp new file mode 100644 index 00000000000..072d8581374 --- /dev/null +++ b/addons/missile_defense/CfgEventHandlers.hpp @@ -0,0 +1,13 @@ +class Extended_PreStart_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preStart)); + }; +}; + +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preInit)); + clientInit = QUOTE(call COMPILE_FILE(XEH_preInitClient)); + serverInit = QUOTE(call COMPILE_FILE(XEH_preInitServer)); + }; +}; diff --git a/addons/missile_defense/XEH_PREP.hpp b/addons/missile_defense/XEH_PREP.hpp new file mode 100644 index 00000000000..5bf111a6f44 --- /dev/null +++ b/addons/missile_defense/XEH_PREP.hpp @@ -0,0 +1,5 @@ +PREP(createSystem); +PREP(registerLauncher); +PREP(registerTracker); +PREP(systemPFH); +PREP(interceptorPFH); diff --git a/addons/missile_defense/XEH_preInit.sqf b/addons/missile_defense/XEH_preInit.sqf new file mode 100644 index 00000000000..aefe9e2cc6e --- /dev/null +++ b/addons/missile_defense/XEH_preInit.sqf @@ -0,0 +1,45 @@ +#include "script_component.hpp" + +ADDON = false; + +#include "initSettings.inc.sqf" + +GVAR(trackingHandle) = -1; +[QGVAR(startTracking), { + if (GVAR(trackingHandle) != -1) exitWith {}; + GVAR(trackingHandle) = ["All", "fired", { + params ["_unit", "", "", "", "", "", "_projectile"]; + + // Handle interceptors from launchers + if (local _unit) then { + private _system = _unit getVariable [QGVAR(system), ""]; + if (_system != "") then { + private _target = _unit getVariable [QEGVAR(missileguidance,target), objNull]; + if !(isNull _target) then { + [QGVAR(registerInterceptor), [_system, _projectile, _target]] call CBA_fnc_serverEvent; + }; + }; + }; + + // Handle profile that should be tracked + TRACE_1("Fired projectile",_projectile); + _projectile setVariable [QGVAR(side), side _unit]; + private _toIntercept = uiNamespace getVariable QGVAR(projectilesToIntercept); + if (local _projectile && { (typeOf _projectile) in _toIntercept }) then { + [QGVAR(track), [_projectile, side _unit]] call CBA_fnc_serverEvent; + }; + _projectile addEventHandler ["SubmunitionCreated", { + params ["_projectile", "_submunitionProjectile"]; + if ((getPosATL _submunitionProjectile) select 2 < 500) exitWith {}; + private _side = _projectile getVariable [QGVAR(side), side _projectile]; + _submunitionProjectile setVariable [QGVAR(side), _side]; + TRACE_1("Submunition created",_submunitionProjectile); + private _toIntercept = uiNamespace getVariable QGVAR(projectilesToIntercept); + if (local _submunitionProjectile && { (typeOf _submunitionProjectile) in _toIntercept }) then { + [QGVAR(track), [_submunitionProjectile, _side]] call CBA_fnc_serverEvent; + }; + }]; + }] call CBA_fnc_addClassEventHandler; +}] call CBA_fnc_addEventHandler; + +ADDON = true; diff --git a/addons/missile_defense/XEH_preInitClient.sqf b/addons/missile_defense/XEH_preInitClient.sqf new file mode 100644 index 00000000000..9ab3f6223b3 --- /dev/null +++ b/addons/missile_defense/XEH_preInitClient.sqf @@ -0,0 +1,20 @@ +#include "script_component.hpp" + +GVAR(destroyRadius) = 20; + +[QGVAR(destroyProjectile), { + params ["_target", "_type", "_position"]; + if !(isNull _target) exitWith { + deleteVehicle _target; + TRACE_1("Destroyed projectile using object",_target); + }; + private _near = nearestObjects [_position, [_type], GVAR(destroyRadius)]; + if (count _near > 0) then { + TRACE_2("Destroying nearby entities of type",_type,_near); + deleteVehicle _near; + } else { + TRACE_2("No nearby entities of type to destroy",_type,_position); + private _nearest = nearestObject [_position, _type]; + deleteVehicle _nearest; + }; +}] call CBA_fnc_addEventHandler; diff --git a/addons/missile_defense/XEH_preInitServer.sqf b/addons/missile_defense/XEH_preInitServer.sqf new file mode 100644 index 00000000000..ba5dd8c76d3 --- /dev/null +++ b/addons/missile_defense/XEH_preInitServer.sqf @@ -0,0 +1,27 @@ +#include "script_component.hpp" + +PREP_RECOMPILE_START; +#include "XEH_PREP.hpp" +PREP_RECOMPILE_END; + +GVAR(systems) = createHashMap; + +[QGVAR(track), { + params ["_projectile", "_side"]; + _projectile setVariable [QGVAR(side), _side]; + TRACE_1("Tracking projectile",_projectile); + { + (_y getOrDefault ["targets_possible", []]) pushBackUnique _projectile; + } forEach GVAR(systems); +}] call CBA_fnc_addEventHandler; + +[QGVAR(registerInterceptor), { + params ["_id", "_interceptor", "_target"]; + private _system = GVAR(systems) getOrDefault [_id, -1]; + if (_system isEqualTo -1) exitWith { + ERROR_1("Missile defense system with ID '%1' does not exist",_id); + }; + _system getOrDefault ["interceptors", []] pushBack [_interceptor, _target, getPosASLVisual _interceptor, _interceptor distance _target]; + TRACE_2("Registered interceptor",_interceptor,_target); +}] call CBA_fnc_addEventHandler; + diff --git a/addons/missile_defense/XEH_preStart.sqf b/addons/missile_defense/XEH_preStart.sqf new file mode 100644 index 00000000000..04af2793383 --- /dev/null +++ b/addons/missile_defense/XEH_preStart.sqf @@ -0,0 +1,24 @@ +#include "script_component.hpp" + +#include "XEH_PREP.hpp" + +GVAR(projectilesToIntercept) = createHashMap; + +#define SIM_TYPES ["shotMissile", "shotShell", "shotRocket"] + +{ + private _simulation = getText (_x >> "simulation"); + if (_simulation in SIM_TYPES) then { + GVAR(projectilesToIntercept) set [configName _x, true]; + }; + private _submunition = getText (_x >> "submunitionAmmo"); + if (_submunition != "") then { + private _submunitionConfig = configFile >> "CfgAmmo" >> _submunition; + private _simulation = getText (_submunitionConfig >> "simulation"); + if (_simulation in SIM_TYPES) then { + GVAR(projectilesToIntercept) set [configName _x, true]; + }; + }; +} forEach ("true" configClasses (configFile >> "CfgAmmo")); + +uiNamespace setVariable [QGVAR(projectilesToIntercept), compileFinal GVAR(projectilesToIntercept)]; diff --git a/addons/missile_defense/config.cpp b/addons/missile_defense/config.cpp new file mode 100644 index 00000000000..a3b64494e97 --- /dev/null +++ b/addons/missile_defense/config.cpp @@ -0,0 +1,18 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + // no point having this system without missile guidance: nothing would happen + requiredAddons[] = {"ace_common","ace_missileguidance"}; + author = ECSTRING(common,ACETeam); + authors[] = {"Brett Mayson", "Dani (TCVM)"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" diff --git a/addons/missile_defense/functions/fnc_createSystem.sqf b/addons/missile_defense/functions/fnc_createSystem.sqf new file mode 100644 index 00000000000..0bdd5318e14 --- /dev/null +++ b/addons/missile_defense/functions/fnc_createSystem.sqf @@ -0,0 +1,54 @@ +#include "..\script_component.hpp" +/* + * Author: Brett Mayson + * Create a missile defense system. + * + * Arguments: + * 0: Sides - The sides that the missile defense system will engage. If not provided, it will engage all sides. + * 1: ID - Optional, The ID of the missile defense system to create. + * + * Return Value: + * - The ID of the created missile defense system. + * + * Example: + * [] call ace_missile_defense_createSystem + * + * Public: Yes + */ + +params ["_sides", ["_id", ""]]; + +if (!isServer) exitWith { + ERROR("missile_defense functions only run on server"); +}; + +if (_id == "") then { + _id = format ["%1-%2", diag_tickTime, count GVAR(systems)]; +}; + +if (_id in GVAR(systems)) exitWith { + ERROR_1("Missile defense system with ID '%1' already exists",_id); +}; + +GVAR(systems) set [_id, createHashMapFromArray [ + ["trackers", []], + ["launchers", []], + ["interceptors", []], + ["sides", _sides], + ["conditions", []], + ["targets_possible", []], + ["targets_pending", []], + ["targets_tracking", []] +]]; + +if (isNil QGVAR(systemIndex)) then { + GVAR(systemIndex) = 0; + [LINKFUNC(systemPFH)] call CBA_fnc_addPerFrameHandler; + [LINKFUNC(interceptorPFH)] call CBA_fnc_addPerFrameHandler; +}; + +TRACE_1("Registered missile defense system",_id); + +[QGVAR(startTracking)] call CBA_fnc_globalEventJIP; + +_id diff --git a/addons/missile_defense/functions/fnc_interceptorPFH.sqf b/addons/missile_defense/functions/fnc_interceptorPFH.sqf new file mode 100644 index 00000000000..5bebc7dd408 --- /dev/null +++ b/addons/missile_defense/functions/fnc_interceptorPFH.sqf @@ -0,0 +1,72 @@ +#include "..\script_component.hpp" +/* + * Author: Brett Mayson + * Processes each interceptor + * + * Arguments: + * 0: Args + * 1: Handle + * + * Return Value: + * None + * + * Example: + * [ace_missile_defense_interceptorPFH] call CBA_fnc_addPerFrameHandler + * + * Public: No + */ + +{ + private _interceptors = _y getOrDefault ["interceptors", []]; + { + _x params ["_projectile", "_target", "_lastPosition", "_lastDistance"]; + if (isNull _projectile) then { + _interceptors deleteAt _forEachIndex; + if !(isNull _target) then { + (_y getOrDefault ["targets_tracking", []]) pushBack _target; + TRACE_2("Interceptor no longer exists",_projectile,_target); + }; + continue; + }; + if (isNull _target) then { + // TODO pick a different target? + TRACE_1("Interceptor target no longer exists, stopping management",_projectile); + _interceptors deleteAt _forEachIndex; + continue; + }; + private _currentPosition = getPosASLVisual _projectile; + private _targetPosition = getPosASLVisual _target; + + private _proximityFuseRange = _projectile getVariable [QGVAR(proximityFuseRange),GVAR(proximityFuseRange)]; + private _proximityFuseFailureChance = _projectile getVariable [QGVAR(proximityFuseFailureChance),GVAR(proximityFuseFailureChance)]; + + private _posDiff = (_currentPosition vectorDiff _lastPosition); + private _lengthSqr = _posDiff vectorDotProduct _posDiff; + private _minDistance = if (_lengthSqr - 0.001 <= 0) then { + _lastPosition vectorDistance _targetPosition // return + } else { + private _d = (_targetPosition vectorDiff _lastPosition) vectorDotProduct (_currentPosition vectorDiff _lastPosition); + private _t = 0 max (1 min (_d / _lengthSqr)); + private _projection = _lastPosition vectorAdd ((_currentPosition vectorDiff _lastPosition) vectorMultiply _t); + _projection vectorDistance _targetPosition // return + }; + + _x set [2, _currentPosition]; + _x set [3, _minDistance]; + + if (_minDistance <= _proximityFuseRange || { _minDistance > _lastDistance }) then { + triggerAmmo _projectile; + _interceptors deleteAt _forEachIndex; + // if we overshot target, dont take out target + if (_minDistance <= _lastDistance && { _proximityFuseFailureChance <= random 1 }) then { + private _explosion = createVehicle ["SmallSecondary", _target, [], 0, "CAN_COLLIDE"]; + [QGVAR(destroyProjectile), [_target, typeOf _target, getPos _target]] call CBA_fnc_globalEvent; + deleteVehicle _target; + TRACE_2("Interceptor detonated on target",_projectile,_target); + } else { + (_y getOrDefault ["targets_tracking", []]) pushBack _target; + TRACE_2("Interceptor failed to intercept target",_projectile,_target); + }; + }; + } forEachReversed _interceptors; +} forEach GVAR(systems); diff --git a/addons/missile_defense/functions/fnc_registerLauncher.sqf b/addons/missile_defense/functions/fnc_registerLauncher.sqf new file mode 100644 index 00000000000..48efc9cdee2 --- /dev/null +++ b/addons/missile_defense/functions/fnc_registerLauncher.sqf @@ -0,0 +1,46 @@ +#include "..\script_component.hpp" +/* + * Author: Brett Mayson + * Register a launcher to a missile defense system. + * + * Arguments: + * 0: ID - The ID of the missile defense system to modify + * 1: Launcher - The launcher object to register. + * + * Return Value: + * None + * + * Example: + * [] call ace_missile_defense_registerLauncher + * + * Public: Yes + */ + +params [ + ["_id", "", [""]], + ["_launcher", objNull, [objNull]] +]; + +if (!isServer) exitWith { + ERROR("missile_defense functions only run on server"); +}; + +private _system = GVAR(systems) getOrDefault [_id, -1]; +if (_system isEqualTo -1) exitWith { + ERROR_1("Missile defense system with ID '%1' does not exist",_id); +}; + +private _launchers = _system getOrDefault ["launchers", []]; +if (_launcher in _launchers) exitWith { + ERROR_1("Missile defense launcher '%1' already registered",_launcher); +}; + +_launcher setVariable [QGVAR(system), _id, true]; +_launcher setVariable [QGVAR(state), LAUNCH_STATE_IDLE]; +_launcher setVariable [QGVAR(lastLaunchTime), 0]; + +_launchers pushBackUnique _launcher; + +[QGVAR(registerLauncher), [_id, _launcher]] call CBA_fnc_globalEvent; + +TRACE_2("Registered missile defense launcher",_launcher,_id); diff --git a/addons/missile_defense/functions/fnc_registerTracker.sqf b/addons/missile_defense/functions/fnc_registerTracker.sqf new file mode 100644 index 00000000000..04016240a4f --- /dev/null +++ b/addons/missile_defense/functions/fnc_registerTracker.sqf @@ -0,0 +1,43 @@ +#include "..\script_component.hpp" +/* + * Author: Brett Mayson + * Register a tracker to a missile defense system. + * + * Arguments: + * 0: ID - The ID of the missile defense system to modify + * 1: Tracker - The tracker object to register. + * 2: Range - The range of the tracker in meters. If not provided, defaults to 3000. + * + * Return Value: + * None + * + * Example: + * [] call ace_missile_defense_registerTracker + * + * Public: No + */ + +params ["_id", "_tracker", ["_range", 3000]]; + +if (!isServer) exitWith { + ERROR("missile_defense functions only run on server"); +}; + +private _system = GVAR(systems) getOrDefault [_id, -1]; +if (_system isEqualTo -1) exitWith { + ERROR_1("Missile defense system with ID '%1' does not exist",_id); +}; + +private _trackers = _system getOrDefault ["trackers", []]; +if (_tracker in _trackers) exitWith { + ERROR_1("Missile defense tracker '%1' already registered",_tracker); +}; + +_tracker setVariable [QGVAR(system), _id, true]; +_tracker setVariable [QGVAR(range), _range, true]; + +_trackers pushBackUnique _tracker; + +[QGVAR(registerTracker), [_id, _tracker]] call CBA_fnc_globalEvent; + +TRACE_2("Registered missile defense tracker",_tracker,_id); diff --git a/addons/missile_defense/functions/fnc_systemPFH.sqf b/addons/missile_defense/functions/fnc_systemPFH.sqf new file mode 100644 index 00000000000..ece0a19244b --- /dev/null +++ b/addons/missile_defense/functions/fnc_systemPFH.sqf @@ -0,0 +1,174 @@ +#include "..\script_component.hpp" +/* + * Author: Brett Mayson + * Processes each missile defense system per frame. + * + * Arguments: + * 0: Args + * 1: Handle + * + * Return Value: + * None + * + * Example: + * [ace_missile_defense_systemPFH] call CBA_fnc_addPerFrameHandler + * + * Public: No + */ + +if (GVAR(systemIndex) > count GVAR(systems) - 1) then { + // If the system index is out of bounds, reset it to 0 + GVAR(systemIndex) = 0; +}; +private _system = GVAR(systems) getOrDefault [(keys GVAR(systems)) select GVAR(systemIndex), -1]; +GVAR(systemIndex) = GVAR(systemIndex) + 1; +if (_system isEqualTo -1) exitWith { + GVAR(systemIndex) = 0; +}; + +// Filter out launchers and trackers that are not alive +{ + private _items = _system getOrDefault [_x, []]; + { + if !(alive _x) then { + _items deleteAt _forEachIndex; + }; + } forEachReversed _items; +} forEach ["launchers", "trackers"]; + +// Move the first target from the possible targets to the pending targets for each missile defense system. +private _target = (_system getOrDefault ["targets_possible", []]) deleteAt 0; +if (!isNil "_target" && {!isNull _target}) then { + private _sides = _system getOrDefault ["sides", []]; + private _side = _target getVariable [QGVAR(side), side _target]; + if (_side in _sides) then { + TRACE_1("Moved pending target",_target); + (_system getOrDefault ["targets_pending", []]) pushBack _target; + } else { + TRACE_2("Target side not in missile defense system sides",_target,_side); + }; +}; + +// Check the first pending target for in range +private _target = (_system getOrDefault ["targets_pending", []]) deleteAt 0; +if (!isNil "_target" && {!isNull _target}) then { + private _seen = false; + { + private _range = _x getVariable [QGVAR(range), 3000]; + if (_target distanceSqr _x <= _range * _range) exitWith { + TRACE_2("Tracker sees target, moved to tracking",_x,_target); + (_system getOrDefault ["targets_tracking", []]) pushBack _target; + _seen = true; + }; + } forEach (_system getOrDefault ["trackers", []]); + if (!_seen) then { + (_system getOrDefault ["targets_pending", []]) pushBack _target; + }; +}; + +// If able, fire at the first tracked target +private _tracked = (_system getOrDefault ["targets_tracking", []]) deleteAt 0; +if (!isNil "_tracked" && {!isNull _tracked}) then { + private _launchers = _system getOrDefault ["launchers", []]; + private _launchers = _launchers select { + private _state = _x getVariable [QGVAR(state), LAUNCH_STATE_IDLE]; + _state == LAUNCH_STATE_IDLE && someAmmo _x + }; + if (count _launchers == 0) exitWith { + TRACE_1("No launchers available to fire at tracked target",_tracked); + _system getOrDefault ["targets_tracking", []] pushBack _tracked; + }; + private _launcher = if (count _launchers > 1) then { + TRACE_1("Scoring launchers for tracked target",_tracked); + private _bestScore = -1; + private _bestLauncher = objNull; + { + private _launcherPos = getPosASLVisual _x; + _launcherPos set [2, (_launcherPos#2) + 2.5]; + if (lineIntersects [_launcherPos, getPosASLVisual _tracked, _x, _tracked]) then { + TRACE_2("Launcher cannot see target, skipping",_x,_tracked); + continue; + }; + + private _distance = _x distance _tracked; + private _distanceFactor = (_distance / 5000) min 1; + + private _trackedDir = getDir _tracked; + private _trackedToLauncher = _tracked getRelDir _x; + + private _angleDiff = abs(_trackedDir - _trackedToLauncher); + if (_angleDiff > 180) then { + _angleDiff = 360 - _angleDiff; + }; + + private _interceptAngle = 180 - _angleDiff; + if (_interceptAngle > 90) then { + _interceptAngle = 180 - _interceptAngle; + }; + private _angleFactor = _interceptAngle / 90; + + private _score = (_angleFactor * 0.7) + (_distanceFactor * 0.3); + TRACE_4("Launcher scoring",_x,_distance,_interceptAngle,_score); + if (_bestScore < 0 || _score < _bestScore) then { + _bestScore = _score; + _bestLauncher = _x; + }; + } forEach _launchers; + _bestLauncher + } else { + _launchers select 0 + }; + if (isNull _launcher) then { + TRACE_1("No launchers could see tracked target",_tracked); + _system getOrDefault ["targets_tracking", []] pushBack _tracked; + } else { + TRACE_2("Launcher selected for tracked target",_launcher,_tracked); + _launcher setVariable [QEGVAR(missileguidance,target), _tracked]; + _launcher setVariable [QGVAR(state), LAUNCH_STATE_TRACKING]; + }; +}; + +// Handle firing and cooldown +{ + private _launcher = _x; + private _state = _launcher getVariable [QGVAR(state), LAUNCH_STATE_IDLE]; + switch (_state) do { + case LAUNCH_STATE_TRACKING: { + private _target = _launcher getVariable [QEGVAR(missileguidance,target), objNull]; + _launcher lookAt getPosVisual _target; + if (isNull _target) then { + TRACE_1("Lost target, returning to idle",_launcher); + _launcher setVariable [QGVAR(state), LAUNCH_STATE_IDLE]; + } else { + private _directionToTarget = (getPosASLVisual _launcher) vectorFromTo (getPosASLVisual _target); + private _turretDirection = _launcher weaponDirection currentWeapon _launcher; + private _localDirection = _launcher vectorWorldToModelVisual _turretDirection; + + private _elevation = 90 - ((_localDirection#1) atan2 (_localDirection#2)); + private _angle = acos (_turretDirection vectorCos _directionToTarget); + + if (_angle <= GVAR(launchAcceptableAngle) && _elevation >= GVAR(launchAcceptableElevation)) then { + _launcher setVariable [QGVAR(state), LAUNCH_STATE_COOLDOWN]; + _launcher setVariable [QGVAR(lastLaunchTime), CBA_missionTime]; + private _turret = [_launcher, (crew _launcher) select 0] call CBA_fnc_turretPath; + [_launcher, _launcher currentWeaponTurret _turret] call BIS_fnc_fire; + [QGVAR(launcherFired), [_launcher, _target, typeOf _target, getPos _target]] call CBA_fnc_globalEvent; + TRACE_2("Launcher fired at target",_launcher,_target); + } else { + if (_angle > GVAR(launchAcceptableAngle)) then { + TRACE_2("Tracking target, angle too wide",_launcher,_angle); + }; + if (_elevation < GVAR(launchAcceptableElevation)) then { + TRACE_2("Tracking target, elevation too low",_launcher,_elevation); + }; + } + }; + }; + case LAUNCH_STATE_COOLDOWN: { + private _lastLaunchTime = _launcher getVariable QGVAR(lastLaunchTime); + if (CBA_missionTime - _lastLaunchTime >= GVAR(timeBetweenLaunches)) then { + _launcher setVariable [QGVAR(state), LAUNCH_STATE_IDLE]; + }; + }; + }; +} forEach (_system getOrDefault ["launchers", []]); diff --git a/addons/missile_defense/initSettings.inc.sqf b/addons/missile_defense/initSettings.inc.sqf new file mode 100644 index 00000000000..0b76e66abf1 --- /dev/null +++ b/addons/missile_defense/initSettings.inc.sqf @@ -0,0 +1,44 @@ +[ + QGVAR(launchAcceptableAngle), "SLIDER", + [LSTRING(launchAcceptableAngle_setting), LSTRING(launchAcceptableAngle_description)], + LSTRING(category), + [1, 60, 20, 0, false], + true, // isGlobal + {[QGVAR(launchAcceptableAngle), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; + +[ + QGVAR(launchAcceptableElevation), "SLIDER", + [LSTRING(launchAcceptableElevation_setting), LSTRING(launchAcceptableElevation_description)], + LSTRING(category), + [-90, 90, 5, 0, false], + true, // isGlobal + {[QGVAR(launchAcceptableElevation), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; + +[ + QGVAR(timeBetweenLaunches), "SLIDER", + [LSTRING(timeBetweenLaunches_setting), LSTRING(timeBetweenLaunches_description)], + LSTRING(category), + [0, 60, 1, 0, false], + true, // isGlobal + {[QGVAR(timeBetweenLaunches), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; + +[ + QGVAR(proximityFuseRange), "SLIDER", + [LSTRING(proximityFuseRange_setting), LSTRING(proximityFuseRange_description)], + LSTRING(category), + [1, 50, 15, 0, false], + true, // isGlobal + {[QGVAR(timeBetweenLaunches), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; + +[ + QGVAR(proximityFuseFailureChance), "SLIDER", + [LSTRING(proximityFuseFailureChance_setting), LSTRING(proximityFuseFailureChance_description)], + LSTRING(category), + [0, 1, 0, 2, true], + true, // isGlobal + {[QGVAR(proximityFuseFailureChance), _this] call EFUNC(common,cbaSettings_settingChanged)} +] call CBA_fnc_addSetting; diff --git a/addons/missile_defense/script_component.hpp b/addons/missile_defense/script_component.hpp new file mode 100644 index 00000000000..a0ea87beacb --- /dev/null +++ b/addons/missile_defense/script_component.hpp @@ -0,0 +1,21 @@ +#define COMPONENT missile_defense +#define COMPONENT_BEAUTIFIED Missile Defense +#include "\z\ace\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define ENABLE_PERFORMANCE_COUNTERS + +#ifdef DEBUG_ENABLED_MISSILE_DEFENSE + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_MISSILE_DEFENSE + #define DEBUG_SETTINGS DEBUG_SETTINGS_MISSILE_DEFENSE +#endif + +#define LAUNCH_STATE_IDLE 0 +#define LAUNCH_STATE_TRACKING 1 +#define LAUNCH_STATE_COOLDOWN 2 + +#include "\z\ace\addons\main\script_macros.hpp" diff --git a/addons/missile_defense/stringtable.xml b/addons/missile_defense/stringtable.xml new file mode 100644 index 00000000000..65fc8b2bdae --- /dev/null +++ b/addons/missile_defense/stringtable.xml @@ -0,0 +1,41 @@ + + + + + ACE Missile Defense + + + Enable the Missile Defense system + + + How many degrees offset the launcher can be before firing + + + Launch Acceptable Angle + + + The minimum number of degrees the launcher has to be pointing up/down before firing + + + Launch Acceptable Elevation + + + Chance for proximity fuse to fail to destroy target + + + Proximity Fuse Failure Chance + + + How close the interceptor has to be to the target in order to detonate + + + Proximity Fuse Range + + + Minimum number of seconds between each launch of an interceptor for a single launcher + + + Time Between Launches + + +