mirror of
https://github.com/spencershepard/RotorOps.git
synced 2025-11-10 15:45:30 +00:00
added imports feature
adds an import feature for getting complex unit arrangements from miz files
This commit is contained in:
parent
58bdc17b00
commit
8160fc29ff
8
Generator/Imports/How to use imports.txt
Normal file
8
Generator/Imports/How to use imports.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
You can put .miz files in this folder to be copied into the generated mission at marker points. This feature is currently very 'alpha' and may produce errors.
|
||||||
|
|
||||||
|
1) Make an empty mission on Cauacasus.
|
||||||
|
2) Place units/objects on the map.
|
||||||
|
3) Make one unit group name: 'ANCHOR' This will represent the point of insertion into the target mission.
|
||||||
|
4) In a Scenario template, place a static object (flag, etc) and call it "IMPORT-[filename of .miz created in first step]"
|
||||||
|
|
||||||
|
Tip: You can change the heading of the imported group by changing the heading of the insertion object.
|
||||||
@ -36,7 +36,7 @@ sys.excepthook = handle_exception
|
|||||||
|
|
||||||
|
|
||||||
maj_version = 0
|
maj_version = 0
|
||||||
minor_version = 4
|
minor_version = 5
|
||||||
version_string = str(maj_version) + "." + str(minor_version)
|
version_string = str(maj_version) + "." + str(minor_version)
|
||||||
scenarios = []
|
scenarios = []
|
||||||
red_forces_files = []
|
red_forces_files = []
|
||||||
|
|||||||
@ -6,11 +6,11 @@ import random
|
|||||||
|
|
||||||
import RotorOpsGroups
|
import RotorOpsGroups
|
||||||
import RotorOpsUnits
|
import RotorOpsUnits
|
||||||
|
import RotorOpsUtils
|
||||||
import time
|
import time
|
||||||
from MissionGenerator import logger
|
from MissionGenerator import logger
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RotorOpsMission:
|
class RotorOpsMission:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -23,6 +23,7 @@ class RotorOpsMission:
|
|||||||
self.sound_directory = self.home_dir + "\sound\embedded"
|
self.sound_directory = self.home_dir + "\sound\embedded"
|
||||||
self.output_dir = self.home_dir + "\Generator\Output"
|
self.output_dir = self.home_dir + "\Generator\Output"
|
||||||
self.assets_dir = self.home_dir + "\Generator/assets"
|
self.assets_dir = self.home_dir + "\Generator/assets"
|
||||||
|
self.imports_dir = self.home_dir + "\Generator\Imports"
|
||||||
|
|
||||||
self.conflict_zones = {}
|
self.conflict_zones = {}
|
||||||
self.staging_zones = {}
|
self.staging_zones = {}
|
||||||
@ -119,6 +120,8 @@ class RotorOpsMission:
|
|||||||
|
|
||||||
self.m.load_file(options["scenario_filename"])
|
self.m.load_file(options["scenario_filename"])
|
||||||
|
|
||||||
|
self.importObjects()
|
||||||
|
|
||||||
if not self.m.country("Combined Joint Task Forces Red") or not self.m.country("Combined Joint Task Forces Blue"):
|
if not self.m.country("Combined Joint Task Forces Red") or not self.m.country("Combined Joint Task Forces Blue"):
|
||||||
failure_msg = "You must include a CombinedJointTaskForcesBlue and CombinedJointTaskForcesRed unit in the scenario template. See the instructions in " + self.scenarios_dir
|
failure_msg = "You must include a CombinedJointTaskForcesBlue and CombinedJointTaskForcesRed unit in the scenario template. See the instructions in " + self.scenarios_dir
|
||||||
return {"success": False, "failure_msg": failure_msg}
|
return {"success": False, "failure_msg": failure_msg}
|
||||||
@ -134,7 +137,6 @@ class RotorOpsMission:
|
|||||||
self.m.add_picture_blue(self.assets_dir + '/briefing2.png')
|
self.m.add_picture_blue(self.assets_dir + '/briefing2.png')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# add zones to target mission
|
# add zones to target mission
|
||||||
zone_names = ["ALPHA", "BRAVO", "CHARLIE", "DELTA"]
|
zone_names = ["ALPHA", "BRAVO", "CHARLIE", "DELTA"]
|
||||||
zone_flag = 101
|
zone_flag = 101
|
||||||
@ -235,6 +237,9 @@ class RotorOpsMission:
|
|||||||
self.addResources(self.sound_directory, self.script_directory)
|
self.addResources(self.sound_directory, self.script_directory)
|
||||||
self.scriptTriggerSetup(options)
|
self.scriptTriggerSetup(options)
|
||||||
|
|
||||||
|
# test adding static objects from a .miz
|
||||||
|
#self.addStatics()
|
||||||
|
|
||||||
#Save the mission file
|
#Save the mission file
|
||||||
os.chdir(self.output_dir)
|
os.chdir(self.output_dir)
|
||||||
output_filename = options["scenario_filename"].removesuffix('.miz') + " " + time.strftime('%a%H%M%S') + '.miz'
|
output_filename = options["scenario_filename"].removesuffix('.miz') + " " + time.strftime('%a%H%M%S') + '.miz'
|
||||||
@ -631,7 +636,7 @@ class RotorOpsMission:
|
|||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
if source_helo:
|
if source_helo and afg:
|
||||||
for unit in afg.units:
|
for unit in afg.units:
|
||||||
unit.pylons = source_helo.pylons
|
unit.pylons = source_helo.pylons
|
||||||
unit.livery_id = source_helo.livery_id
|
unit.livery_id = source_helo.livery_id
|
||||||
@ -661,10 +666,10 @@ class RotorOpsMission:
|
|||||||
group_size=group_size)
|
group_size=group_size)
|
||||||
zone_attack(afg, airport)
|
zone_attack(afg, airport)
|
||||||
|
|
||||||
if source_plane:
|
if source_plane:
|
||||||
for unit in afg.units:
|
for unit in afg.units:
|
||||||
unit.pylons = source_plane.pylons
|
unit.pylons = source_plane.pylons
|
||||||
unit.livery_id = source_plane.livery_id
|
unit.livery_id = source_plane.livery_id
|
||||||
|
|
||||||
if options["e_transport_helos"]:
|
if options["e_transport_helos"]:
|
||||||
source_helo = None
|
source_helo = None
|
||||||
@ -690,10 +695,10 @@ class RotorOpsMission:
|
|||||||
afg.late_activation = True
|
afg.late_activation = True
|
||||||
afg.units[0].skill = dcs.unit.Skill.Excellent
|
afg.units[0].skill = dcs.unit.Skill.Excellent
|
||||||
|
|
||||||
if source_helo:
|
if source_helo:
|
||||||
for unit in afg.units:
|
for unit in afg.units:
|
||||||
unit.pylons = source_helo.pylons
|
unit.pylons = source_helo.pylons
|
||||||
unit.livery_id = source_helo.livery_id
|
unit.livery_id = source_helo.livery_id
|
||||||
|
|
||||||
def scriptTriggerSetup(self, options):
|
def scriptTriggerSetup(self, options):
|
||||||
|
|
||||||
@ -841,3 +846,23 @@ class RotorOpsMission:
|
|||||||
self.m.triggerrules.triggers.append(trig)
|
self.m.triggerrules.triggers.append(trig)
|
||||||
|
|
||||||
|
|
||||||
|
def addStatics(self):
|
||||||
|
os.chdir(self.home_dir + "/Generator/Statics")
|
||||||
|
logger.info("Looking for .miz files in '" + os.getcwd())
|
||||||
|
dest_point = self.conflict_zones["ALPHA"].position
|
||||||
|
grps = RotorOpsUtils.extractUnits.toPoint("test.miz", dest_point, 180)
|
||||||
|
for grp in grps:
|
||||||
|
self.m.country("Combined Joint Task Forces Blue").add_vehicle_group(grp)
|
||||||
|
|
||||||
|
def importObjects(self):
|
||||||
|
os.chdir(self.imports_dir)
|
||||||
|
logger.info("Looking for import .miz files in '" + os.getcwd())
|
||||||
|
for group in self.m.country("Combined Joint Task Forces Blue").static_group:
|
||||||
|
prefix = "IMPORT-"
|
||||||
|
if group.name.find(prefix) == 0:
|
||||||
|
filename = group.name.removeprefix(prefix) + ".miz"
|
||||||
|
i = RotorOpsUtils.ImportObjects(filename)
|
||||||
|
i.anchorByGroupName("ANCHOR")
|
||||||
|
i.copyTo(self.m, group.units[0].position)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import math
|
import math
|
||||||
import dcs
|
import dcs
|
||||||
|
from MissionGenerator import logger
|
||||||
|
|
||||||
|
|
||||||
def getDistance(point1=dcs.Point, point2=dcs.Point):
|
def getDistance(point1=dcs.Point, point2=dcs.Point):
|
||||||
@ -15,3 +16,111 @@ def getDistance(point1=dcs.Point, point2=dcs.Point):
|
|||||||
def convertMeterToNM(meters=int):
|
def convertMeterToNM(meters=int):
|
||||||
nm = meters / 1852
|
nm = meters / 1852
|
||||||
return nm
|
return nm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ImportObjects:
|
||||||
|
|
||||||
|
def __init__(self, mizfile, ref_point=None, ref_heading=0):
|
||||||
|
self.source_mission = dcs.mission.Mission()
|
||||||
|
self.source_mission.load_file(mizfile)
|
||||||
|
self.ref_heading = ref_heading
|
||||||
|
if ref_point:
|
||||||
|
self.ref_point = ref_point
|
||||||
|
else:
|
||||||
|
self.ref_point = dcs.Point(self.source_mission.terrain.bullseye_blue["x"], self.source_mission.terrain.bullseye_blue["y"])
|
||||||
|
|
||||||
|
|
||||||
|
def anchorByGroupName(self, group_name):
|
||||||
|
group = self.source_mission.find_group(group_name)
|
||||||
|
if group:
|
||||||
|
self.ref_point = group.units[0].position
|
||||||
|
self.ref_heading = group.units[0].heading
|
||||||
|
else:
|
||||||
|
logger.warning("Unable to find group for anchor.")
|
||||||
|
|
||||||
|
|
||||||
|
def copyTo(self, mission, dest_point=None, dest_heading=0):
|
||||||
|
if not dest_point:
|
||||||
|
dest_point = dcs.Point(mission.terrain.bullseye_blue["x"], mission.terrain.bullseye_blue["y"])
|
||||||
|
|
||||||
|
#iterate over group types first?
|
||||||
|
for side in "red", "blue":
|
||||||
|
coalition = self.source_mission.coalition.get(side)
|
||||||
|
for country in coalition.countries:
|
||||||
|
|
||||||
|
group_types = [coalition.countries[country].static_group, coalition.countries[country].vehicle_group, coalition.countries[country].helicopter_group, coalition.countries[country].plane_group,
|
||||||
|
coalition.countries[country].ship_group]
|
||||||
|
|
||||||
|
for index, group_type in enumerate(group_types):
|
||||||
|
for group in group_type:
|
||||||
|
self.groupToPoint(group, self.ref_point, dest_point, self.ref_heading, dest_heading)
|
||||||
|
if index == 0:
|
||||||
|
mission.country(country).add_static_group(group)
|
||||||
|
elif index == 1:
|
||||||
|
mission.country(country).add_vehicle_group(group)
|
||||||
|
elif index == 2:
|
||||||
|
#mission.country(country).add_helicopter_group(group)
|
||||||
|
print("helicopter groups not available for import")
|
||||||
|
elif index == 3:
|
||||||
|
#mission.country(country).add_plane_group(group)
|
||||||
|
print("plane groups not available for import")
|
||||||
|
elif index == 4:
|
||||||
|
mission.country(country).add_ship_group(group)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def groupToPoint(group, ref_point, dest_point, ref_heading=0, dest_heading=0):
|
||||||
|
for unit in group.units:
|
||||||
|
heading_to_unit = dcs.mapping.heading_between_points(ref_point.x, ref_point.y, unit.position.x,
|
||||||
|
unit.position.y)
|
||||||
|
new_heading_to_unit = dest_heading + heading_to_unit
|
||||||
|
unit_distance = ref_point.distance_to_point(unit.position)
|
||||||
|
unit.position = dest_point.point_from_heading(new_heading_to_unit, unit_distance)
|
||||||
|
return group
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# class extractUnits:
|
||||||
|
#
|
||||||
|
# @staticmethod
|
||||||
|
# def toPoint(filename, group_type, dest_point, dest_heading=0, side="blue"):
|
||||||
|
# print("Attempting to extract units from " + filename + " relative to 'HELO_FARP' initial point.")
|
||||||
|
#
|
||||||
|
# source_mission = dcs.mission.Mission()
|
||||||
|
# source_mission.load_file(filename)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# # country = source_mission.country('Combined Joint Task Forces Blue')
|
||||||
|
# # country.find
|
||||||
|
#
|
||||||
|
# #group_types = []
|
||||||
|
#
|
||||||
|
# groups = []
|
||||||
|
#
|
||||||
|
# for country in source_mission.coalition.get(side).countries:
|
||||||
|
#
|
||||||
|
# ref_point = country.find_static_group("HELO_FARP").position #units position instead of group?
|
||||||
|
# ref_heading = country.find_static_group("HELO_FARP").heading
|
||||||
|
# group_types = [country.static_group, country.vehicle_group, country.helicopter_group, country.plane_group, country.ship_group]
|
||||||
|
#
|
||||||
|
# for group_type in group_types:
|
||||||
|
# for group in group_type:
|
||||||
|
# for unit in group.units:
|
||||||
|
# x_rel = ref_point.x - unit.position.x
|
||||||
|
# y_rel = ref_point.y - unit.position.y
|
||||||
|
# #heading_rel = ref_heading - unit.heading # heading of unit relative to heading of the reference object
|
||||||
|
# heading_to_unit = dcs.mapping.heading_between_points(ref_point.x, ref_point.y, unit.position.x, unit.position.y)
|
||||||
|
# new_heading_to_unit = dest_heading + heading_to_unit
|
||||||
|
# unit_distance = ref_point.distance_to_point(unit.position)
|
||||||
|
# unit.position = dest_point.point_from_heading(new_heading_to_unit, unit_distance)
|
||||||
|
#
|
||||||
|
# # unit.position.x = x - x_rel
|
||||||
|
# # unit.position.y = y - y_rel
|
||||||
|
#
|
||||||
|
# groups.append(group)
|
||||||
|
# return groups
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
43
RotorOps.lua
43
RotorOps.lua
@ -1,5 +1,5 @@
|
|||||||
RotorOps = {}
|
RotorOps = {}
|
||||||
RotorOps.version = "1.2.6"
|
RotorOps.version = "1.2.7"
|
||||||
local debug = true
|
local debug = true
|
||||||
|
|
||||||
|
|
||||||
@ -345,6 +345,7 @@ end
|
|||||||
function RotorOps.isUnitInZone(unit, zone_name)
|
function RotorOps.isUnitInZone(unit, zone_name)
|
||||||
local zone = trigger.misc.getZone(zone_name)
|
local zone = trigger.misc.getZone(zone_name)
|
||||||
local distance = getDistance(unit:getPoint(), zone.point)
|
local distance = getDistance(unit:getPoint(), zone.point)
|
||||||
|
--local distance = mist.utils.get2DDist(unit:getPoint(), zone.point)
|
||||||
if distance <= zone.radius then
|
if distance <= zone.radius then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
@ -1497,3 +1498,43 @@ function RotorOps.spawnTranspHelos(troops, max_drops)
|
|||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- USEFUL PUBLIC 'LUA PREDICATE' FUNCTIONS FOR MISSION EDITOR TRIGGERS
|
||||||
|
|
||||||
|
--determine if any players have broken a defined ceiling above ground level
|
||||||
|
function RotorOps.predPlayerMaxAGL(max_agl, hide_display)
|
||||||
|
for uName, uData in pairs(mist.DBs.humansByName) do
|
||||||
|
local player_unit = Unit.getByName(uData.unitName)
|
||||||
|
if player_unit then
|
||||||
|
local player_pos = player_unit:getPosition().p
|
||||||
|
local terrain_height = land.getHeight({x = player_pos.x, y = player_pos.z})
|
||||||
|
local player_agl = player_pos.y - terrain_height
|
||||||
|
if player_agl > max_agl then
|
||||||
|
env.info(uData.unitName.." broke the AGL limit of "..max_agl)
|
||||||
|
if not hide_display then
|
||||||
|
trigger.action.outText(uData.unitName.." is above the maximum altitude of "..max_agl.."m AGL.", 1, true)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--determine if any players are in a zone (not currently working)
|
||||||
|
function RotorOps.predPlayerInZone(zone_name)
|
||||||
|
local players_in_zone = 0
|
||||||
|
for uName, uData in pairs(mist.DBs.humansByName) do
|
||||||
|
local player_unit = Unit.getByName(uData.unitName)
|
||||||
|
if player_unit and RotorOps.isUnitInZone(player_unit, zone_name) then
|
||||||
|
players_in_zone = players_in_zone + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if players_in_zone > 0 then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user