mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
JTAC support
This commit is contained in:
parent
bff33e6992
commit
2a50768db1
@ -19,6 +19,9 @@
|
|||||||
* **[Mission Generator]** The briefing will now contain the carrier ATC frequency
|
* **[Mission Generator]** The briefing will now contain the carrier ATC frequency
|
||||||
* **[Mission Generator]** The briefing contains a small situation update.
|
* **[Mission Generator]** The briefing contains a small situation update.
|
||||||
* **[Mission Generator]** Previously destroyed units are visible in the mission. (And added a performance settings to disable this behaviour)
|
* **[Mission Generator]** Previously destroyed units are visible in the mission. (And added a performance settings to disable this behaviour)
|
||||||
|
* **[Campaign Generator]** Added Tarawa in caucasus campaigns
|
||||||
|
* **[Campaign Generator]** Tuned the various existing campaign parameters
|
||||||
|
* **[Campaign Generator]** Added small campaign : "Russia" on Caucasus Theater
|
||||||
|
|
||||||
## Fixed issues :
|
## Fixed issues :
|
||||||
* **[Mission Generator]** Carrier will sail into the wind, not in the same direction
|
* **[Mission Generator]** Carrier will sail into the wind, not in the same direction
|
||||||
|
|||||||
@ -46,5 +46,5 @@ Australia_2005 = {
|
|||||||
"HMAS Adelaide"
|
"HMAS Adelaide"
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator"
|
"ArleighBurkeGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,5 +54,5 @@ BLUEFOR_COLDWAR = {
|
|||||||
"LHA-4 Nassau",
|
"LHA-4 Nassau",
|
||||||
"LHA-5 Peleliu"
|
"LHA-5 Peleliu"
|
||||||
], "boat": [
|
], "boat": [
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,5 +61,5 @@ BLUEFOR_COLDWAR_A4 = {
|
|||||||
], "boat": [
|
], "boat": [
|
||||||
], "requirements": {
|
], "requirements": {
|
||||||
"Community A-4E": "https://heclak.github.io/community-a4e-c/",
|
"Community A-4E": "https://heclak.github.io/community-a4e-c/",
|
||||||
}
|
}, "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,5 +64,5 @@ BLUEFOR_COLDWAR_MODS = {
|
|||||||
], "requirements": {
|
], "requirements": {
|
||||||
"MB-339A": "http://www.freccetricolorivirtuali.net/",
|
"MB-339A": "http://www.freccetricolorivirtuali.net/",
|
||||||
"Community A-4E": "https://heclak.github.io/community-a4e-c/",
|
"Community A-4E": "https://heclak.github.io/community-a4e-c/",
|
||||||
}
|
}, "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,5 +78,5 @@ BLUEFOR_MODERN = {
|
|||||||
"LHA-5 Peleliu"
|
"LHA-5 Peleliu"
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,5 +39,5 @@ Canada_2005 = {
|
|||||||
Ticonderoga_class,
|
Ticonderoga_class,
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator"
|
"ArleighBurkeGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,5 +73,5 @@ China_2010 = {
|
|||||||
"002 Shandong",
|
"002 Shandong",
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"Type54GroupGenerator"
|
"Type54GroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -42,5 +42,5 @@ France_1995 = {
|
|||||||
AirDefence.SAM_Roland_ADS
|
AirDefence.SAM_Roland_ADS
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -57,5 +57,5 @@ France_2005 = {
|
|||||||
"L9015 Dixmude"
|
"L9015 Dixmude"
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -75,5 +75,5 @@ France_2005_Modded = {
|
|||||||
], "requirements": {
|
], "requirements": {
|
||||||
"frenchpack V3.5": "https://forums.eagle.ru/showthread.php?t=279974",
|
"frenchpack V3.5": "https://forums.eagle.ru/showthread.php?t=279974",
|
||||||
"RAFALE 2.5.5": "https://www.digitalcombatsimulator.com/fr/files/3307478/",
|
"RAFALE 2.5.5": "https://www.digitalcombatsimulator.com/fr/files/3307478/",
|
||||||
}
|
}, "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -51,5 +51,5 @@ India_2010 = {
|
|||||||
"INS Vikramaditya"
|
"INS Vikramaditya"
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator", "MolniyaGroupGenerator"
|
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator", "MolniyaGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -35,5 +35,5 @@ Israel_2000 = {
|
|||||||
AirDefence.SAM_Avenger_M1097
|
AirDefence.SAM_Avenger_M1097
|
||||||
], "boat": [
|
], "boat": [
|
||||||
"ArleighBurkeGroupGenerator"
|
"ArleighBurkeGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -44,5 +44,5 @@ Italy_1990 = {
|
|||||||
"Cavour",
|
"Cavour",
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"OliverHazardPerryGroupGenerator"
|
"OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,5 +48,5 @@ Italy_1990_MB339 = {
|
|||||||
"OliverHazardPerryGroupGenerator"
|
"OliverHazardPerryGroupGenerator"
|
||||||
], "requirements": {
|
], "requirements": {
|
||||||
"MB-339A": "http://www.freccetricolorivirtuali.net/",
|
"MB-339A": "http://www.freccetricolorivirtuali.net/",
|
||||||
}
|
}, "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,5 +50,5 @@ Japan_2005 = {
|
|||||||
"Ise",
|
"Ise",
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator"
|
"ArleighBurkeGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,5 +34,5 @@ Netherlands_1990 = {
|
|||||||
AirDefence.SAM_Avenger_M1097
|
AirDefence.SAM_Avenger_M1097
|
||||||
], "boat": [
|
], "boat": [
|
||||||
"OliverHazardPerryGroupGenerator"
|
"OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,5 +36,5 @@ Pakistan_2015 = {
|
|||||||
AirDefence.AAA_ZU_23_Closed
|
AirDefence.AAA_ZU_23_Closed
|
||||||
], "boat": [
|
], "boat": [
|
||||||
"Type54GroupGenerator", "OliverHazardPerryGroupGenerator"
|
"Type54GroupGenerator", "OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,5 +46,5 @@ Spain_1990 = {
|
|||||||
"Juan Carlos I",
|
"Juan Carlos I",
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"OliverHazardPerryGroupGenerator"
|
"OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -27,5 +27,5 @@ Sweden_1990 = {
|
|||||||
],
|
],
|
||||||
"shorad": [
|
"shorad": [
|
||||||
AirDefence.SAM_Avenger_M1097
|
AirDefence.SAM_Avenger_M1097
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -38,5 +38,5 @@ Turkey_2005 = {
|
|||||||
AirDefence.SPAAA_ZSU_23_4_Shilka
|
AirDefence.SPAAA_ZSU_23_4_Shilka
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"OliverHazardPerryGroupGenerator"
|
"OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -32,5 +32,5 @@ UAE_2005 = {
|
|||||||
Armed_speedboat,
|
Armed_speedboat,
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"OliverHazardPerryGroupGenerator"
|
"OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -48,5 +48,5 @@ UnitedKingdom_1990 = {
|
|||||||
"HMS Ark Royal",
|
"HMS Ark Royal",
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -61,5 +61,5 @@ USA_1990 = {
|
|||||||
"LHA-5 Peleliu"
|
"LHA-5 Peleliu"
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
"ArleighBurkeGroupGenerator", "OliverHazardPerryGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
@ -66,5 +66,5 @@ USA_2005 = {
|
|||||||
"LHA-5 Peleliu"
|
"LHA-5 Peleliu"
|
||||||
], "boat":[
|
], "boat":[
|
||||||
"ArleighBurkeGroupGenerator"
|
"ArleighBurkeGroupGenerator"
|
||||||
]
|
], "has_jtac": True
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,6 +75,7 @@ class Game:
|
|||||||
self.__culling_points = self.compute_conflicts_position()
|
self.__culling_points = self.compute_conflicts_position()
|
||||||
self.__frontlineData = []
|
self.__frontlineData = []
|
||||||
self.__destroyed_units = []
|
self.__destroyed_units = []
|
||||||
|
self.jtacs = []
|
||||||
self.savepath = ""
|
self.savepath = ""
|
||||||
|
|
||||||
self.sanitize_sides()
|
self.sanitize_sides()
|
||||||
|
|||||||
@ -157,6 +157,7 @@ class Operation:
|
|||||||
self.airgen.generate_flights(cp, country, self.game.planners[cp.id])
|
self.airgen.generate_flights(cp, country, self.game.planners[cp.id])
|
||||||
|
|
||||||
# Generate ground units on frontline everywhere
|
# Generate ground units on frontline everywhere
|
||||||
|
self.game.jtacs = []
|
||||||
for player_cp, enemy_cp in self.game.theater.conflicts(True):
|
for player_cp, enemy_cp in self.game.theater.conflicts(True):
|
||||||
conflict = Conflict.frontline_cas_conflict(self.attacker_name, self.defender_name,
|
conflict = Conflict.frontline_cas_conflict(self.attacker_name, self.defender_name,
|
||||||
self.current_mission.country(self.attacker_country),
|
self.current_mission.country(self.attacker_country),
|
||||||
@ -175,14 +176,14 @@ class Operation:
|
|||||||
else:
|
else:
|
||||||
self.current_mission.groundControl.red_tactical_commander = self.ca_slots
|
self.current_mission.groundControl.red_tactical_commander = self.ca_slots
|
||||||
|
|
||||||
# triggers
|
# Triggers
|
||||||
if self.game.is_player_attack(self.conflict.attackers_country):
|
if self.game.is_player_attack(self.conflict.attackers_country):
|
||||||
cp = self.conflict.from_cp
|
cp = self.conflict.from_cp
|
||||||
else:
|
else:
|
||||||
cp = self.conflict.to_cp
|
cp = self.conflict.to_cp
|
||||||
self.triggersgen.generate()
|
self.triggersgen.generate()
|
||||||
|
|
||||||
# options
|
# Options
|
||||||
self.forcedoptionsgen.generate()
|
self.forcedoptionsgen.generate()
|
||||||
|
|
||||||
# Generate Visuals Smoke Effects
|
# Generate Visuals Smoke Effects
|
||||||
@ -195,6 +196,18 @@ class Operation:
|
|||||||
load_mist.add_action(DoScript(String(f.read())))
|
load_mist.add_action(DoScript(String(f.read())))
|
||||||
self.current_mission.triggerrules.triggers.append(load_mist)
|
self.current_mission.triggerrules.triggers.append(load_mist)
|
||||||
|
|
||||||
|
# Load Ciribob's JTACAutoLase script
|
||||||
|
load_autolase = TriggerStart(comment="Load JTAC script")
|
||||||
|
with open("./resources/scripts/JTACAutoLase.lua") as f:
|
||||||
|
|
||||||
|
script = f.read()
|
||||||
|
script = script + "\n"
|
||||||
|
for jtac in self.game.jtacs:
|
||||||
|
script = script + "\n" + "JTACAutoLase('" + str(jtac[2]) + "', " + str(jtac[1]) + ", true, \"vehicle\")" + "\n"
|
||||||
|
|
||||||
|
load_autolase.add_action(DoScript(String(script)))
|
||||||
|
self.current_mission.triggerrules.triggers.append(load_autolase)
|
||||||
|
|
||||||
load_dcs_libe = TriggerStart(comment="Load DCS Liberation Script")
|
load_dcs_libe = TriggerStart(comment="Load DCS Liberation Script")
|
||||||
with open("./resources/scripts/dcs_liberation.lua") as f:
|
with open("./resources/scripts/dcs_liberation.lua") as f:
|
||||||
script = f.read()
|
script = f.read()
|
||||||
|
|||||||
@ -24,6 +24,7 @@ class Settings:
|
|||||||
self.sams = True # Legacy parameter do not use
|
self.sams = True # Legacy parameter do not use
|
||||||
self.cold_start = False # Legacy parameter do not use
|
self.cold_start = False # Legacy parameter do not use
|
||||||
self.version = None
|
self.version = None
|
||||||
|
self.include_jtac_if_available = True
|
||||||
|
|
||||||
# Performance oriented
|
# Performance oriented
|
||||||
self.perf_red_alert_state = True
|
self.perf_red_alert_state = True
|
||||||
|
|||||||
14
gen/armor.py
14
gen/armor.py
@ -97,6 +97,20 @@ class GroundConflictGenerator:
|
|||||||
self.plan_action_for_groups(self.player_stance, player_groups, enemy_groups, self.conflict.heading + 90, self.conflict.from_cp, self.conflict.to_cp)
|
self.plan_action_for_groups(self.player_stance, player_groups, enemy_groups, self.conflict.heading + 90, self.conflict.from_cp, self.conflict.to_cp)
|
||||||
self.plan_action_for_groups(self.enemy_stance, enemy_groups, player_groups, self.conflict.heading - 90, self.conflict.to_cp, self.conflict.from_cp)
|
self.plan_action_for_groups(self.enemy_stance, enemy_groups, player_groups, self.conflict.heading - 90, self.conflict.to_cp, self.conflict.from_cp)
|
||||||
|
|
||||||
|
# Add JTAC
|
||||||
|
if "has_jtac" in self.game.player_faction and self.game.player_faction["has_jtac"] and self.game.settings.include_jtac_if_available:
|
||||||
|
n = "JTAC" + str(self.conflict.from_cp.id) + str(self.conflict.to_cp.id)
|
||||||
|
code = 1688 + len(self.game.jtacs)
|
||||||
|
jtac = self.mission.flight_group(country=self.mission.country(self.game.player_country),
|
||||||
|
name=n,
|
||||||
|
aircraft_type=MQ_9_Reaper,
|
||||||
|
position=position[0],
|
||||||
|
airport=None,
|
||||||
|
altitude=5000)
|
||||||
|
jtac.points[0].tasks.append(OrbitAction(5000, 300, OrbitAction.OrbitPattern.Circle))
|
||||||
|
jtac.points[0].tasks.append(SetInvisibleCommand(True))
|
||||||
|
jtac.points[0].tasks.append(SetImmortalCommand(True))
|
||||||
|
self.game.jtacs.append(("Frontline " + self.conflict.from_cp.name + "/" + self.conflict.to_cp.name, code, n))
|
||||||
|
|
||||||
def gen_infantry_group_for_group(self, group, is_player, side:Country, forward_heading):
|
def gen_infantry_group_for_group(self, group, is_player, side:Country, forward_heading):
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,8 @@ class BriefingGenerator:
|
|||||||
self.targets = []
|
self.targets = []
|
||||||
self.waypoints = []
|
self.waypoints = []
|
||||||
|
|
||||||
|
self.jtacs = []
|
||||||
|
|
||||||
def append_frequency(self, name: str, frequency: str):
|
def append_frequency(self, name: str, frequency: str):
|
||||||
self.freqs.append((name, frequency))
|
self.freqs.append((name, frequency))
|
||||||
|
|
||||||
@ -109,6 +111,12 @@ class BriefingGenerator:
|
|||||||
self.description += "ICLS Channel : " + str(cp.icls) + "\n"
|
self.description += "ICLS Channel : " + str(cp.icls) + "\n"
|
||||||
self.description += "-" * 50 + "\n"
|
self.description += "-" * 50 + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
self.description += "JTACS [F-10 Menu] : \n"
|
||||||
|
self.description += "==================="
|
||||||
|
for jtac in self.game.jtacs:
|
||||||
|
self.description += str(jtac[0]) + " -- Code : " + str(jtac[1]) + "\n"
|
||||||
|
|
||||||
self.m.set_description_text(self.description)
|
self.m.set_description_text(self.description)
|
||||||
|
|
||||||
self.m.add_picture_blue(os.path.abspath("./resources/ui/splash_screen.png"))
|
self.m.add_picture_blue(os.path.abspath("./resources/ui/splash_screen.png"))
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class QMissionPlanning(QDialog):
|
|||||||
super(QMissionPlanning, self).__init__()
|
super(QMissionPlanning, self).__init__()
|
||||||
self.game = game
|
self.game = game
|
||||||
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||||
self.setMinimumSize(1000, 420)
|
self.setMinimumSize(1000, 440)
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
self.setWindowTitle("Mission Preparation")
|
self.setWindowTitle("Mission Preparation")
|
||||||
self.setWindowIcon(EVENT_ICONS["strike"])
|
self.setWindowIcon(EVENT_ICONS["strike"])
|
||||||
|
|||||||
@ -166,13 +166,23 @@ class QSettingsWindow(QDialog):
|
|||||||
self.generate_marks.setChecked(self.game.settings.generate_marks)
|
self.generate_marks.setChecked(self.game.settings.generate_marks)
|
||||||
self.generate_marks.toggled.connect(self.applySettings)
|
self.generate_marks.toggled.connect(self.applySettings)
|
||||||
|
|
||||||
|
|
||||||
|
if not hasattr(self.game.settings, "include_jtac_if_available"):
|
||||||
|
self.game.settings.include_jtac_if_available = True
|
||||||
|
|
||||||
|
self.include_jtac_if_available = QCheckBox()
|
||||||
|
self.include_jtac_if_available.setChecked(self.game.settings.include_jtac_if_available)
|
||||||
|
self.include_jtac_if_available.toggled.connect(self.applySettings)
|
||||||
|
|
||||||
self.gameplayLayout.addWidget(QLabel("Use Supercarrier Module"), 0, 0)
|
self.gameplayLayout.addWidget(QLabel("Use Supercarrier Module"), 0, 0)
|
||||||
self.gameplayLayout.addWidget(self.supercarrier, 0, 1, Qt.AlignRight)
|
self.gameplayLayout.addWidget(self.supercarrier, 0, 1, Qt.AlignRight)
|
||||||
self.gameplayLayout.addWidget(QLabel("Put Objective Markers on Map"), 1, 0)
|
self.gameplayLayout.addWidget(QLabel("Put Objective Markers on Map"), 1, 0)
|
||||||
self.gameplayLayout.addWidget(self.generate_marks, 1, 1, Qt.AlignRight)
|
self.gameplayLayout.addWidget(self.generate_marks, 1, 1, Qt.AlignRight)
|
||||||
|
self.gameplayLayout.addWidget(QLabel("Include JTAC (If available)"), 2, 0)
|
||||||
|
self.gameplayLayout.addWidget(self.include_jtac_if_available, 2, 1, Qt.AlignRight)
|
||||||
|
|
||||||
self.performance = QGroupBox("Performance")
|
self.performance = QGroupBox("Performance")
|
||||||
self.performanceLayout = QGridLayout();
|
self.performanceLayout = QGridLayout()
|
||||||
self.performanceLayout.setAlignment(Qt.AlignTop)
|
self.performanceLayout.setAlignment(Qt.AlignTop)
|
||||||
self.performance.setLayout(self.performanceLayout)
|
self.performance.setLayout(self.performanceLayout)
|
||||||
|
|
||||||
@ -288,6 +298,7 @@ class QSettingsWindow(QDialog):
|
|||||||
self.game.settings.map_coalition_visibility = self.mapVisibiitySelection.currentData()
|
self.game.settings.map_coalition_visibility = self.mapVisibiitySelection.currentData()
|
||||||
self.game.settings.external_views_allowed = self.ext_views.isChecked()
|
self.game.settings.external_views_allowed = self.ext_views.isChecked()
|
||||||
self.game.settings.generate_marks = self.generate_marks.isChecked()
|
self.game.settings.generate_marks = self.generate_marks.isChecked()
|
||||||
|
self.game.settings.include_jtac_if_available = self.include_jtac_if_available.isChecked()
|
||||||
|
|
||||||
print(self.game.settings.map_coalition_visibility)
|
print(self.game.settings.map_coalition_visibility)
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
729
resources/scripts/JTACAutoLase.lua
Normal file
729
resources/scripts/JTACAutoLase.lua
Normal file
@ -0,0 +1,729 @@
|
|||||||
|
--[[
|
||||||
|
JTAC Automatic Targeting and Laser Script
|
||||||
|
|
||||||
|
Allows a JTAC to mark and hold an IR and Laser point on a target allowing TGP's to lock onto the lase and ease
|
||||||
|
of target location using NV Goggles
|
||||||
|
|
||||||
|
The JTAC will automatically switch targets when a target is destroyed or goes out of Line of Sight
|
||||||
|
|
||||||
|
NOTE: LOS doesn't include buildings or tree's... Sorry!
|
||||||
|
|
||||||
|
The script can also be useful in daylight by enabling the JTAC to mark enemy positions with Smoke.
|
||||||
|
The JTAC will only move the smoke to the target every 5 minutes (to stop a huge trail of smoke markers) unless the target
|
||||||
|
is destroyed, in which case the new target will be marked straight away with smoke.
|
||||||
|
|
||||||
|
You can also enable an F10 menu option for coalition units allowing the JTAC(s) to report their current status.
|
||||||
|
|
||||||
|
If a JTAC is down it won't report in.
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
|
||||||
|
Place JTAC units on the map with the mission editor putting each JTAC in it's own group containing only itself and no
|
||||||
|
other units. Name the group something easy to remember e.g. JTAC1 and make sure the JTAC units have a unique name which must
|
||||||
|
not be the same as the group name. The editor should do this for you but be careful if you copy and paste.
|
||||||
|
|
||||||
|
Load the script at the start of the mission with a Trigger Once or as the init script of the mission
|
||||||
|
|
||||||
|
Run the code below as a DO SCRIPT at the start of the mission, or after a delay if you prefer
|
||||||
|
|
||||||
|
JTACAutoLase('JTAC1', 1688)
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
JTACAutoLase('JTAC1', 1688, false,"all") - means no smoke marks for this jtac and it will target all ground troops
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
JTACAutoLase('JTAC1', 1688, true,"vehicle") - means smoke marks for this jtac and it will target ONLY ground vehicles
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
JTACAutoLase('JTAC1', 1688, true,"troop") - means smoke marks for this jtac and it will target ONLY ground troops
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
JTACAutoLase('JTAC1', 1688, true,"all", 4) - means BLUE smoke marks for this jtac and it will target all ground troops
|
||||||
|
|
||||||
|
Where JTAC1 is the Group name of the JTAC Group with one and only one JTAC unit.
|
||||||
|
|
||||||
|
The script doesn't care if the unit isn't activated when run, as it'll automatically activate when the JTAC is activated in
|
||||||
|
the mission but there can be a delay of up to 30 seconds after activation for the JTAC to start searching for targets.
|
||||||
|
|
||||||
|
You can also run the code at any time if a JTAC is dynamically added to the map as long as you know the Group name of the JTAC.
|
||||||
|
|
||||||
|
Last Edit: 21/04/2015
|
||||||
|
|
||||||
|
Change log:
|
||||||
|
Added new config of JTAC smoke colour globally or per JTAC
|
||||||
|
Added new config of JTAC targetting to either target only troops or vehicles or all
|
||||||
|
Added new induvidual config of JTAC smoke and location which will override global setting
|
||||||
|
Added Lat / Lon + MGRS to JTAC Target position
|
||||||
|
Changed Lasing method to update laser marker rather than create and destroy
|
||||||
|
- This gives much better tracking behaviour!
|
||||||
|
Fixed JTAC lasing through terrain.
|
||||||
|
Fixed Lase staying on when JTAC Dies
|
||||||
|
Fixed Lase staying on when target dies and there are no other targets
|
||||||
|
Added Radio noise when message is shown
|
||||||
|
Stop multiple JTACS targeting the same target
|
||||||
|
|
||||||
|
|
||||||
|
Parts of MIST used. Source is https://github.com/mrSkortch/MissionScriptingTools/blob/master/mist.lua
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
-- CONFIG
|
||||||
|
JTAC_maxDistance = 50000 -- How far a JTAC can "see" in meters (with LOS)
|
||||||
|
|
||||||
|
JTAC_smokeOn = true -- enables marking of target with smoke, can be overriden by the JTACAutoLase in editor
|
||||||
|
|
||||||
|
JTAC_smokeColour = 1 -- Green = 0 , Red = 1, White = 2, Orange = 3, Blue = 4
|
||||||
|
|
||||||
|
JTAC_jtacStatusF10 = true -- enables F10 JTAC Status menu
|
||||||
|
|
||||||
|
JTAC_location = true -- shows location in JTAC message, can be overriden by the JTACAutoLase in editor
|
||||||
|
|
||||||
|
JTAC_lock = "all" -- "vehicle" OR "troop" OR "all" forces JTAC to only lock vehicles or troops or all ground units
|
||||||
|
|
||||||
|
-- END CONFIG
|
||||||
|
|
||||||
|
-- BE CAREFUL MODIFYING BELOW HERE
|
||||||
|
|
||||||
|
GLOBAL_JTAC_LASE = {}
|
||||||
|
GLOBAL_JTAC_IR = {}
|
||||||
|
GLOBAL_JTAC_SMOKE = {}
|
||||||
|
GLOBAL_JTAC_UNITS = {} -- list of JTAC units for f10 command
|
||||||
|
GLOBAL_JTAC_CURRENT_TARGETS = {}
|
||||||
|
GLOBAL_JTAC_RADIO_ADDED = {} --keeps track of who's had the radio command added
|
||||||
|
GLOBAL_JTAC_LASER_CODES = {} -- keeps track of laser codes for jtac
|
||||||
|
|
||||||
|
|
||||||
|
function JTACAutoLase(jtacGroupName, laserCode,smoke,lock,colour)
|
||||||
|
|
||||||
|
if smoke == nil then
|
||||||
|
|
||||||
|
smoke = JTAC_smokeOn
|
||||||
|
end
|
||||||
|
|
||||||
|
if lock == nil then
|
||||||
|
|
||||||
|
lock = JTAC_lock
|
||||||
|
end
|
||||||
|
|
||||||
|
if colour == nil then
|
||||||
|
colour = JTAC_smokeColour
|
||||||
|
end
|
||||||
|
|
||||||
|
GLOBAL_JTAC_LASER_CODES[jtacGroupName] = laserCode
|
||||||
|
|
||||||
|
local jtacGroup = getGroup(jtacGroupName)
|
||||||
|
local jtacUnit
|
||||||
|
|
||||||
|
if jtacGroup == nil or #jtacGroup == 0 then
|
||||||
|
|
||||||
|
notify("JTAC Group " .. jtacGroupName .. " KIA!", 10)
|
||||||
|
|
||||||
|
--remove from list
|
||||||
|
GLOBAL_JTAC_UNITS[jtacGroupName] = nil
|
||||||
|
|
||||||
|
cleanupJTAC(jtacGroupName)
|
||||||
|
|
||||||
|
return
|
||||||
|
else
|
||||||
|
|
||||||
|
jtacUnit = jtacGroup[1]
|
||||||
|
--add to list
|
||||||
|
GLOBAL_JTAC_UNITS[jtacGroupName] = jtacUnit:getName()
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- search for current unit
|
||||||
|
|
||||||
|
if jtacUnit:isActive() == false then
|
||||||
|
|
||||||
|
cleanupJTAC(jtacGroupName)
|
||||||
|
|
||||||
|
env.info(jtacGroupName .. ' Not Active - Waiting 30 seconds')
|
||||||
|
timer.scheduleFunction(timerJTACAutoLase, { jtacGroupName, laserCode,smoke,lock,colour}, timer.getTime() + 30)
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local enemyUnit = getCurrentUnit(jtacUnit, jtacGroupName)
|
||||||
|
|
||||||
|
if enemyUnit == nil and GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] ~= nil then
|
||||||
|
|
||||||
|
local tempUnitInfo = GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName]
|
||||||
|
|
||||||
|
-- env.info("TEMP UNIT INFO: " .. tempUnitInfo.name .. " " .. tempUnitInfo.unitType)
|
||||||
|
|
||||||
|
local tempUnit = Unit.getByName(tempUnitInfo.name)
|
||||||
|
|
||||||
|
if tempUnit ~= nil and tempUnit:getLife() > 0 and tempUnit:isActive() == true then
|
||||||
|
notify(jtacGroupName .. " target " .. tempUnitInfo.unitType .. " lost. Scanning for Targets. ", 10)
|
||||||
|
else
|
||||||
|
notify(jtacGroupName .. " target " .. tempUnitInfo.unitType .. " KIA. Good Job! Scanning for Targets. ", 10)
|
||||||
|
end
|
||||||
|
|
||||||
|
--remove from smoke list
|
||||||
|
GLOBAL_JTAC_SMOKE[tempUnitInfo.name] = nil
|
||||||
|
|
||||||
|
-- remove from target list
|
||||||
|
GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] = nil
|
||||||
|
|
||||||
|
--stop lasing
|
||||||
|
cancelLase(jtacGroupName)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if enemyUnit == nil then
|
||||||
|
enemyUnit = findNearestVisibleEnemy(jtacUnit,lock)
|
||||||
|
|
||||||
|
if enemyUnit ~= nil then
|
||||||
|
|
||||||
|
-- store current target for easy lookup
|
||||||
|
GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] = { name = enemyUnit:getName(), unitType = enemyUnit:getTypeName(), unitId = enemyUnit:getID() }
|
||||||
|
|
||||||
|
notify(jtacGroupName .. " lasing new target " .. enemyUnit:getTypeName() .. '. CODE: ' .. laserCode ..getPositionString(enemyUnit) , 10)
|
||||||
|
|
||||||
|
-- create smoke
|
||||||
|
if smoke == true then
|
||||||
|
|
||||||
|
--create first smoke
|
||||||
|
createSmokeMarker(enemyUnit,colour)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if enemyUnit ~= nil then
|
||||||
|
|
||||||
|
laseUnit(enemyUnit, jtacUnit, jtacGroupName, laserCode)
|
||||||
|
|
||||||
|
-- env.info('Timer timerSparkleLase '..jtacGroupName.." "..laserCode.." "..enemyUnit:getName())
|
||||||
|
timer.scheduleFunction(timerJTACAutoLase, { jtacGroupName, laserCode, smoke,lock,colour }, timer.getTime() + 1)
|
||||||
|
|
||||||
|
|
||||||
|
if smoke == true then
|
||||||
|
local nextSmokeTime = GLOBAL_JTAC_SMOKE[enemyUnit:getName()]
|
||||||
|
|
||||||
|
--recreate smoke marker after 5 mins
|
||||||
|
if nextSmokeTime ~= nil and nextSmokeTime < timer.getTime() then
|
||||||
|
|
||||||
|
createSmokeMarker(enemyUnit, colour)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
-- env.info('LASE: No Enemies Nearby')
|
||||||
|
|
||||||
|
-- stop lazing the old spot
|
||||||
|
cancelLase(jtacGroupName)
|
||||||
|
-- env.info('Timer Slow timerSparkleLase '..jtacGroupName.." "..laserCode.." "..enemyUnit:getName())
|
||||||
|
|
||||||
|
timer.scheduleFunction(timerJTACAutoLase, { jtacGroupName, laserCode, smoke,lock,colour }, timer.getTime() + 5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- used by the timer function
|
||||||
|
function timerJTACAutoLase(args)
|
||||||
|
|
||||||
|
JTACAutoLase(args[1], args[2], args[3],args[4])
|
||||||
|
end
|
||||||
|
|
||||||
|
function cleanupJTAC(jtacGroupName)
|
||||||
|
-- clear laser - just in case
|
||||||
|
cancelLase(jtacGroupName)
|
||||||
|
|
||||||
|
-- Cleanup
|
||||||
|
GLOBAL_JTAC_UNITS[jtacGroupName] = nil
|
||||||
|
|
||||||
|
GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function notify(message, displayFor)
|
||||||
|
|
||||||
|
|
||||||
|
trigger.action.outTextForCoalition(coalition.side.BLUE, message, displayFor)
|
||||||
|
trigger.action.outSoundForCoalition(coalition.side.BLUE, "radiobeep.ogg")
|
||||||
|
end
|
||||||
|
|
||||||
|
function createSmokeMarker(enemyUnit,colour)
|
||||||
|
|
||||||
|
--recreate in 5 mins
|
||||||
|
GLOBAL_JTAC_SMOKE[enemyUnit:getName()] = timer.getTime() + 300.0
|
||||||
|
|
||||||
|
-- move smoke 2 meters above target for ease
|
||||||
|
local enemyPoint = enemyUnit:getPoint()
|
||||||
|
trigger.action.smoke({ x = enemyPoint.x, y = enemyPoint.y + 2.0, z = enemyPoint.z }, colour)
|
||||||
|
end
|
||||||
|
|
||||||
|
function cancelLase(jtacGroupName)
|
||||||
|
|
||||||
|
--local index = "JTAC_"..jtacUnit:getID()
|
||||||
|
|
||||||
|
local tempLase = GLOBAL_JTAC_LASE[jtacGroupName]
|
||||||
|
|
||||||
|
if tempLase ~= nil then
|
||||||
|
Spot.destroy(tempLase)
|
||||||
|
GLOBAL_JTAC_LASE[jtacGroupName] = nil
|
||||||
|
|
||||||
|
-- env.info('Destroy laze '..index)
|
||||||
|
|
||||||
|
tempLase = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local tempIR = GLOBAL_JTAC_IR[jtacGroupName]
|
||||||
|
|
||||||
|
if tempIR ~= nil then
|
||||||
|
Spot.destroy(tempIR)
|
||||||
|
GLOBAL_JTAC_IR[jtacGroupName] = nil
|
||||||
|
|
||||||
|
-- env.info('Destroy laze '..index)
|
||||||
|
|
||||||
|
tempIR = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function laseUnit(enemyUnit, jtacUnit, jtacGroupName, laserCode)
|
||||||
|
|
||||||
|
--cancelLase(jtacGroupName)
|
||||||
|
|
||||||
|
local spots = {}
|
||||||
|
|
||||||
|
local enemyVector = enemyUnit:getPoint()
|
||||||
|
local enemyVectorUpdated = { x = enemyVector.x, y = enemyVector.y + 2.0, z = enemyVector.z }
|
||||||
|
|
||||||
|
local oldLase = GLOBAL_JTAC_LASE[jtacGroupName]
|
||||||
|
local oldIR = GLOBAL_JTAC_IR[jtacGroupName]
|
||||||
|
|
||||||
|
if oldLase == nil or oldIR == nil then
|
||||||
|
|
||||||
|
-- create lase
|
||||||
|
|
||||||
|
local status, result = pcall(function()
|
||||||
|
spots['irPoint'] = Spot.createInfraRed(jtacUnit, { x = 0, y = 2.0, z = 0 }, enemyVectorUpdated)
|
||||||
|
spots['laserPoint'] = Spot.createLaser(jtacUnit, { x = 0, y = 2.0, z = 0 }, enemyVectorUpdated, laserCode)
|
||||||
|
return spots
|
||||||
|
end)
|
||||||
|
|
||||||
|
if not status then
|
||||||
|
env.error('ERROR: ' .. assert(result), false)
|
||||||
|
else
|
||||||
|
if result.irPoint then
|
||||||
|
|
||||||
|
-- env.info(jtacUnit:getName() .. ' placed IR Pointer on '..enemyUnit:getName())
|
||||||
|
|
||||||
|
GLOBAL_JTAC_IR[jtacGroupName] = result.irPoint --store so we can remove after
|
||||||
|
|
||||||
|
end
|
||||||
|
if result.laserPoint then
|
||||||
|
|
||||||
|
-- env.info(jtacUnit:getName() .. ' is Lasing '..enemyUnit:getName()..'. CODE:'..laserCode)
|
||||||
|
|
||||||
|
GLOBAL_JTAC_LASE[jtacGroupName] = result.laserPoint
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- update lase
|
||||||
|
|
||||||
|
if oldLase~=nil then
|
||||||
|
oldLase:setPoint(enemyVectorUpdated)
|
||||||
|
end
|
||||||
|
|
||||||
|
if oldIR ~= nil then
|
||||||
|
oldIR:setPoint(enemyVectorUpdated)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get currently selected unit and check they're still in range
|
||||||
|
function getCurrentUnit(jtacUnit, jtacGroupName)
|
||||||
|
|
||||||
|
|
||||||
|
local unit = nil
|
||||||
|
|
||||||
|
if GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName] ~= nil then
|
||||||
|
unit = Unit.getByName(GLOBAL_JTAC_CURRENT_TARGETS[jtacGroupName].name)
|
||||||
|
end
|
||||||
|
|
||||||
|
local tempPoint = nil
|
||||||
|
local tempDist = nil
|
||||||
|
local tempPosition = nil
|
||||||
|
|
||||||
|
local jtacPosition = jtacUnit:getPosition()
|
||||||
|
local jtacPoint = jtacUnit:getPoint()
|
||||||
|
|
||||||
|
if unit ~= nil and unit:getLife() > 0 and unit:isActive() == true then
|
||||||
|
|
||||||
|
-- calc distance
|
||||||
|
tempPoint = unit:getPoint()
|
||||||
|
-- tempPosition = unit:getPosition()
|
||||||
|
|
||||||
|
tempDist = getDistance(tempPoint.x, tempPoint.z, jtacPoint.x, jtacPoint.z)
|
||||||
|
if tempDist < JTAC_maxDistance then
|
||||||
|
-- calc visible
|
||||||
|
|
||||||
|
-- check slightly above the target as rounding errors can cause issues, plus the unit has some height anyways
|
||||||
|
local offsetEnemyPos = { x = tempPoint.x, y = tempPoint.y + 2.0, z = tempPoint.z }
|
||||||
|
local offsetJTACPos = { x = jtacPoint.x, y = jtacPoint.y + 2.0, z = jtacPoint.z }
|
||||||
|
|
||||||
|
if land.isVisible(offsetEnemyPos, offsetJTACPos) then
|
||||||
|
return unit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Find nearest enemy to JTAC that isn't blocked by terrain
|
||||||
|
function findNearestVisibleEnemy(jtacUnit, targetType)
|
||||||
|
|
||||||
|
local x = 1
|
||||||
|
local i = 1
|
||||||
|
|
||||||
|
local units = nil
|
||||||
|
local groupName = nil
|
||||||
|
|
||||||
|
local nearestUnit = nil
|
||||||
|
local nearestDistance = JTAC_maxDistance
|
||||||
|
|
||||||
|
local redGroups = coalition.getGroups(1, Group.Category.GROUND)
|
||||||
|
|
||||||
|
local jtacPoint = jtacUnit:getPoint()
|
||||||
|
local jtacPosition = jtacUnit:getPosition()
|
||||||
|
|
||||||
|
local tempPoint = nil
|
||||||
|
local tempPosition = nil
|
||||||
|
|
||||||
|
local tempDist = nil
|
||||||
|
|
||||||
|
-- finish this function
|
||||||
|
for i = 1, #redGroups do
|
||||||
|
if redGroups[i] ~= nil then
|
||||||
|
groupName = redGroups[i]:getName()
|
||||||
|
units = getGroup(groupName)
|
||||||
|
if #units > 0 then
|
||||||
|
|
||||||
|
for x = 1, #units do
|
||||||
|
|
||||||
|
--check to see if a JTAC has already targeted this unit
|
||||||
|
local targeted = alreadyTarget(jtacUnit,units[x])
|
||||||
|
local allowedTarget = true
|
||||||
|
|
||||||
|
if targetType == "vehicle" then
|
||||||
|
|
||||||
|
allowedTarget = isVehicle(units[x])
|
||||||
|
|
||||||
|
elseif targetType == "troop" then
|
||||||
|
|
||||||
|
allowedTarget = isInfantry(units[x])
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if units[x]:isActive() == true and targeted == false and allowedTarget == true then
|
||||||
|
|
||||||
|
-- calc distance
|
||||||
|
tempPoint = units[x]:getPoint()
|
||||||
|
-- tempPosition = units[x]:getPosition()
|
||||||
|
|
||||||
|
tempDist = getDistance(tempPoint.x, tempPoint.z, jtacPoint.x, jtacPoint.z)
|
||||||
|
|
||||||
|
-- env.info("tempDist" ..tempDist)
|
||||||
|
-- env.info("JTAC_maxDistance" ..JTAC_maxDistance)
|
||||||
|
|
||||||
|
if tempDist < JTAC_maxDistance and tempDist < nearestDistance then
|
||||||
|
|
||||||
|
local offsetEnemyPos = { x = tempPoint.x, y = tempPoint.y + 2.0, z = tempPoint.z }
|
||||||
|
local offsetJTACPos = { x = jtacPoint.x, y = jtacPoint.y + 2.0, z = jtacPoint.z }
|
||||||
|
|
||||||
|
|
||||||
|
-- calc visible
|
||||||
|
if land.isVisible(offsetEnemyPos, offsetJTACPos) then
|
||||||
|
|
||||||
|
nearestDistance = tempDist
|
||||||
|
nearestUnit = units[x]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if nearestUnit == nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return nearestUnit
|
||||||
|
end
|
||||||
|
-- tests whether the unit is targeted by another JTAC
|
||||||
|
function alreadyTarget(jtacUnit, enemyUnit)
|
||||||
|
|
||||||
|
for y , jtacTarget in pairs(GLOBAL_JTAC_CURRENT_TARGETS) do
|
||||||
|
|
||||||
|
if jtacTarget.unitId == enemyUnit:getID() then
|
||||||
|
-- env.info("ALREADY TARGET")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Returns only alive units from group but the group / unit may not be active
|
||||||
|
|
||||||
|
function getGroup(groupName)
|
||||||
|
|
||||||
|
local groupUnits = Group.getByName(groupName)
|
||||||
|
|
||||||
|
local filteredUnits = {} --contains alive units
|
||||||
|
local x = 1
|
||||||
|
|
||||||
|
if groupUnits ~= nil then
|
||||||
|
|
||||||
|
groupUnits = groupUnits:getUnits()
|
||||||
|
|
||||||
|
if groupUnits ~= nil and #groupUnits > 0 then
|
||||||
|
for x = 1, #groupUnits do
|
||||||
|
if groupUnits[x]:getLife() > 0 then
|
||||||
|
table.insert(filteredUnits, groupUnits[x])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return filteredUnits
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Distance measurement between two positions, assume flat world
|
||||||
|
|
||||||
|
function getDistance(xUnit, yUnit, xZone, yZone)
|
||||||
|
local xDiff = xUnit - xZone
|
||||||
|
local yDiff = yUnit - yZone
|
||||||
|
|
||||||
|
return math.sqrt(xDiff * xDiff + yDiff * yDiff)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- gets the JTAC status and displays to coalition units
|
||||||
|
function getJTACStatus()
|
||||||
|
|
||||||
|
--returns the status of all JTAC units
|
||||||
|
|
||||||
|
local jtacGroupName = nil
|
||||||
|
local jtacUnit = nil
|
||||||
|
local jtacUnitName = nil
|
||||||
|
|
||||||
|
local message = "JTAC STATUS: \n\n"
|
||||||
|
|
||||||
|
for jtacGroupName, jtacUnitName in pairs(GLOBAL_JTAC_UNITS) do
|
||||||
|
|
||||||
|
--look up units
|
||||||
|
jtacUnit = Unit.getByName(jtacUnitName)
|
||||||
|
|
||||||
|
if jtacUnit ~= nil and jtacUnit:getLife() > 0 and jtacUnit:isActive() == true then
|
||||||
|
|
||||||
|
local enemyUnit = getCurrentUnit(jtacUnit, jtacGroupName)
|
||||||
|
|
||||||
|
local laserCode = GLOBAL_JTAC_LASER_CODES[jtacGroupName]
|
||||||
|
|
||||||
|
if laserCode == nil then
|
||||||
|
laserCode = "UNKNOWN"
|
||||||
|
end
|
||||||
|
|
||||||
|
if enemyUnit ~= nil and enemyUnit:getLife() > 0 and enemyUnit:isActive() == true then
|
||||||
|
message = message .. "" .. jtacGroupName .. " targeting " .. enemyUnit:getTypeName().. " CODE: ".. laserCode .. getPositionString(enemyUnit) .. "\n"
|
||||||
|
else
|
||||||
|
message = message .. "" .. jtacGroupName .. " searching for targets" .. getPositionString(jtacUnit) .."\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
notify(message, 10)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Radio command for players (F10 Menu)
|
||||||
|
|
||||||
|
function addRadioCommands()
|
||||||
|
|
||||||
|
--looop over all players and add command
|
||||||
|
-- missionCommands.addCommandForCoalition( coalition.side.BLUE, "JTAC Status" ,nil, getJTACStatus ,nil)
|
||||||
|
|
||||||
|
timer.scheduleFunction(addRadioCommands, nil, timer.getTime() + 10)
|
||||||
|
|
||||||
|
local blueGroups = coalition.getGroups(coalition.side.BLUE)
|
||||||
|
local x = 1
|
||||||
|
|
||||||
|
if blueGroups ~= nil then
|
||||||
|
for x, tmpGroup in pairs(blueGroups) do
|
||||||
|
|
||||||
|
|
||||||
|
local index = "GROUP_" .. Group.getID(tmpGroup)
|
||||||
|
-- env.info("adding command for "..index)
|
||||||
|
if GLOBAL_JTAC_RADIO_ADDED[index] == nil then
|
||||||
|
-- env.info("about command for "..index)
|
||||||
|
missionCommands.addCommandForGroup(Group.getID(tmpGroup), "JTAC Status", nil, getJTACStatus, nil)
|
||||||
|
GLOBAL_JTAC_RADIO_ADDED[index] = true
|
||||||
|
-- env.info("Added command for " .. index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function isInfantry(unit)
|
||||||
|
|
||||||
|
local typeName = unit:getTypeName()
|
||||||
|
|
||||||
|
--type coerce tostring
|
||||||
|
typeName = string.lower(typeName.."")
|
||||||
|
|
||||||
|
local soldierType = { "infantry","paratrooper","stinger","manpad"}
|
||||||
|
|
||||||
|
for key,value in pairs(soldierType) do
|
||||||
|
if string.match(typeName, value) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- assume anything that isnt soldier is vehicle
|
||||||
|
function isVehicle(unit)
|
||||||
|
|
||||||
|
if isInfantry(unit) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function getPositionString(unit)
|
||||||
|
|
||||||
|
if JTAC_location == false then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
local latLngStr = latLngString(unit,3)
|
||||||
|
|
||||||
|
local mgrsString = MGRSString(coord.LLtoMGRS(coord.LOtoLL(unit:getPosition().p)),5)
|
||||||
|
|
||||||
|
return " @ " .. latLngStr .. " - MGRS "..mgrsString
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- source of Function MIST - https://github.com/mrSkortch/MissionScriptingTools/blob/master/mist.lua
|
||||||
|
function latLngString(unit, acc)
|
||||||
|
|
||||||
|
local lat, lon = coord.LOtoLL(unit:getPosition().p)
|
||||||
|
|
||||||
|
local latHemi, lonHemi
|
||||||
|
if lat > 0 then
|
||||||
|
latHemi = 'N'
|
||||||
|
else
|
||||||
|
latHemi = 'S'
|
||||||
|
end
|
||||||
|
|
||||||
|
if lon > 0 then
|
||||||
|
lonHemi = 'E'
|
||||||
|
else
|
||||||
|
lonHemi = 'W'
|
||||||
|
end
|
||||||
|
|
||||||
|
lat = math.abs(lat)
|
||||||
|
lon = math.abs(lon)
|
||||||
|
|
||||||
|
local latDeg = math.floor(lat)
|
||||||
|
local latMin = (lat - latDeg)*60
|
||||||
|
|
||||||
|
local lonDeg = math.floor(lon)
|
||||||
|
local lonMin = (lon - lonDeg)*60
|
||||||
|
|
||||||
|
-- degrees, decimal minutes.
|
||||||
|
latMin = roundNumber(latMin, acc)
|
||||||
|
lonMin = roundNumber(lonMin, acc)
|
||||||
|
|
||||||
|
if latMin == 60 then
|
||||||
|
latMin = 0
|
||||||
|
latDeg = latDeg + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if lonMin == 60 then
|
||||||
|
lonMin = 0
|
||||||
|
lonDeg = lonDeg + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
local minFrmtStr -- create the formatting string for the minutes place
|
||||||
|
if acc <= 0 then -- no decimal place.
|
||||||
|
minFrmtStr = '%02d'
|
||||||
|
else
|
||||||
|
local width = 3 + acc -- 01.310 - that's a width of 6, for example.
|
||||||
|
minFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
|
||||||
|
end
|
||||||
|
|
||||||
|
return string.format('%02d', latDeg) .. ' ' .. string.format(minFrmtStr, latMin) .. '\'' .. latHemi .. ' '
|
||||||
|
.. string.format('%02d', lonDeg) .. ' ' .. string.format(minFrmtStr, lonMin) .. '\'' .. lonHemi
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- source of Function MIST - https://github.com/mrSkortch/MissionScriptingTools/blob/master/mist.lua
|
||||||
|
function MGRSString(MGRS, acc)
|
||||||
|
if acc == 0 then
|
||||||
|
return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph
|
||||||
|
else
|
||||||
|
return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph .. ' ' .. string.format('%0' .. acc .. 'd', roundNumber(MGRS.Easting/(10^(5-acc)), 0))
|
||||||
|
.. ' ' .. string.format('%0' .. acc .. 'd', roundNumber(MGRS.Northing/(10^(5-acc)), 0))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- From http://lua-users.org/wiki/SimpleRound
|
||||||
|
function roundNumber(num, idp)
|
||||||
|
local mult = 10^(idp or 0)
|
||||||
|
return math.floor(num * mult + 0.5) / mult
|
||||||
|
end
|
||||||
|
|
||||||
|
-- add the radio commands
|
||||||
|
if JTAC_jtacStatusF10 == true then
|
||||||
|
timer.scheduleFunction(addRadioCommands, nil, timer.getTime() + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--DEBUG FUNCTIONS - IGNORE
|
||||||
|
--function print_functions(o)
|
||||||
|
--
|
||||||
|
-- for key,value in pairs(getmetatable(o)) do
|
||||||
|
-- env.info(tostring(key) .." ".. tostring(value))
|
||||||
|
-- end
|
||||||
|
--end
|
||||||
|
--
|
||||||
|
--function dump_table(o)
|
||||||
|
-- if type(o) == 'table' then
|
||||||
|
-- local s = '{ '
|
||||||
|
-- for k,v in pairs(o) do
|
||||||
|
-- if type(k) ~= 'number' then k = '"'..k..'"' end
|
||||||
|
-- s = s .. '['..k..'] = ' .. dump_table(v) .. ','
|
||||||
|
-- end
|
||||||
|
-- return s .. '} '
|
||||||
|
-- else
|
||||||
|
-- return tostring(o)
|
||||||
|
-- end
|
||||||
|
--end
|
||||||
Binary file not shown.
@ -3,7 +3,7 @@ import pickle
|
|||||||
from dcs.mission import Mission
|
from dcs.mission import Mission
|
||||||
from dcs.planes import A_10C
|
from dcs.planes import A_10C
|
||||||
|
|
||||||
for terrain in ["gulf", "nev", "channel", "normandy"]:
|
for terrain in ["cau"]:
|
||||||
print("Terrain " + terrain)
|
print("Terrain " + terrain)
|
||||||
m = Mission()
|
m = Mission()
|
||||||
m.load_file("./{}_terrain.miz".format(terrain))
|
m.load_file("./{}_terrain.miz".format(terrain))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user