From 4373d896611c92d87d0d03f8fe34d41b52428727 Mon Sep 17 00:00:00 2001 From: Khopa Date: Wed, 3 Jun 2020 00:45:44 +0200 Subject: [PATCH] WIP on CAP, and AI units can starts from ground uncontrolled instead of using late activation. --- gen/aircraft.py | 77 +++++-- gen/flights/ai_flight_planner.py | 131 +++++++++--- gen/flights/flight.py | 20 ++ requirements.txt | 1 + resources/customized_payloads/Su-24M.lua | 250 +++++++++++------------ theater/controlpoint.py | 1 + 6 files changed, 310 insertions(+), 170 deletions(-) diff --git a/gen/aircraft.py b/gen/aircraft.py index 73b28749..9ca000cc 100644 --- a/gen/aircraft.py +++ b/gen/aircraft.py @@ -1,12 +1,12 @@ -from dcs.action import ActivateGroup +from dcs.action import ActivateGroup, AITaskPush from dcs.condition import TimeAfter, CoalitionHasAirdrome from dcs.helicopters import UH_1H from dcs.terrain.terrain import NoParkingSlotError from dcs.triggers import TriggerOnce, Event from game.settings import Settings -from gen.flights.ai_flight_planner import FlightPlanner -from gen.flights.flight import Flight, FlightType +from gen.flights.ai_flight_planner import FlightPlanner, CAP_DEFAULT_ENGAGE_DISTANCE, nm_to_meter +from gen.flights.flight import Flight, FlightType, FlightWaypointType from .conflictgen import * from .naming import * from .triggergen import TRIGGER_WAYPOINT_OFFSET @@ -354,23 +354,48 @@ class AircraftConflictGenerator: def setup_group_activation_trigger(self, flight, group): if flight.scheduled_in > 0 and flight.client_count == 0: - group.late_activation = True - activation_trigger = TriggerOnce(Event.NoEvent, "LiberationActivationTriggerForGroup" + str(group.id)) - activation_trigger.add_condition(TimeAfter(seconds=flight.scheduled_in*60)) - if(flight.from_cp.cptype == ControlPointType.AIRBASE): - if not flight.from_cp.captured: - activation_trigger.add_condition(CoalitionHasAirdrome(self.game.get_player_coalition_id(), flight.from_cp.id)) - else: - activation_trigger.add_condition(CoalitionHasAirdrome(self.game.get_enemy_coalition_id(), flight.from_cp.id)) + if flight.start_type != "In Flight": + group.late_activation = False + group.uncontrolled = True + + activation_trigger = TriggerOnce(Event.NoEvent, "LiberationControlTriggerForGroup" + str(group.id)) + activation_trigger.add_condition(TimeAfter(seconds=flight.scheduled_in * 60)) + if (flight.from_cp.cptype == ControlPointType.AIRBASE): + if flight.from_cp.captured: + activation_trigger.add_condition( + CoalitionHasAirdrome(self.game.get_player_coalition_id(), flight.from_cp.id)) + else: + activation_trigger.add_condition( + CoalitionHasAirdrome(self.game.get_enemy_coalition_id(), flight.from_cp.id)) + + group.add_trigger_action(StartCommand()) + activation_trigger.add_action(AITaskPush(group.id, len(group.tasks))) + self.m.triggerrules.triggers.append(activation_trigger) + print("ADD TRIG CTRL") + else: + group.late_activation = True + activation_trigger = TriggerOnce(Event.NoEvent, "LiberationActivationTriggerForGroup" + str(group.id)) + activation_trigger.add_condition(TimeAfter(seconds=flight.scheduled_in*60)) + + if(flight.from_cp.cptype == ControlPointType.AIRBASE): + if flight.from_cp.captured: + activation_trigger.add_condition(CoalitionHasAirdrome(self.game.get_player_coalition_id(), flight.from_cp.id)) + else: + activation_trigger.add_condition(CoalitionHasAirdrome(self.game.get_enemy_coalition_id(), flight.from_cp.id)) - activation_trigger.add_action(ActivateGroup(group.id)) - self.m.triggerrules.triggers.append(activation_trigger) + activation_trigger.add_action(ActivateGroup(group.id)) + self.m.triggerrules.triggers.append(activation_trigger) def generate_planned_flight(self, cp, country, flight:Flight): try: - if flight.start_type == "In Flight" or flight.client_count == 0: + if flight.client_count == 0: + flight.start_type = "Warm" + + print(flight.start_type) + + if flight.start_type == "In Flight": group = self._generate_group( name=namegen.next_unit_name(country, cp.id, flight.unit_type), side=country, @@ -406,6 +431,7 @@ class AircraftConflictGenerator: start_type=st) except Exception: # Generated when there is no place on Runway or on Parking Slots + flight.start_type = "In Flight" group = self._generate_group( name=namegen.next_unit_name(country, cp.id, flight.unit_type), side=country, @@ -427,8 +453,27 @@ class AircraftConflictGenerator: def setup_group_as_cap_flight(self, group, flight): self._setup_group(group, CAP, flight.client_count) - for point in flight.points: - group.add_waypoint(Point(point.x,point.y), point.alt) + + #group.points[0].tasks.clear() + #group.tasks.clear() + #group.tasks.append(EngageTargets(max_distance=40, targets=[Targets.All.Air])) + #group.tasks.append(EngageTargets(max_distance=nm_to_meter(120), targets=[Targets.All.Air])) + + for i, point in enumerate(flight.points): + + if not point.only_for_player or (point.only_for_player and flight.client_count > 0): + pt = group.add_waypoint(Point(point.x, point.y), point.alt) + + if point.waypoint_type == FlightWaypointType.PATROL_TRACK: + action = OrbitAction(altitude=pt.alt, pattern=OrbitAction.OrbitPattern.RaceTrack) + pt.tasks.append(action) + #for tgt in point.targets: + # if hasattr(tgt, "position"): + # engagetgt = EngageTargetsInZone(tgt.position, radius=CAP_DEFAULT_ENGAGE_DISTANCE, targets=[Targets.All.Air]) + # pt.tasks.append(engagetgt) + elif point.waypoint_type == FlightWaypointType.LANDING_POINT: + pt.type = "Land" + def setup_group_as_cas_flight(self, group, flight): group.task = CAS.name diff --git a/gen/flights/ai_flight_planner.py b/gen/flights/ai_flight_planner.py index 05b53267..fc4bc777 100644 --- a/gen/flights/ai_flight_planner.py +++ b/gen/flights/ai_flight_planner.py @@ -6,7 +6,24 @@ import random from game import db from gen import Conflict from gen.flights.ai_flight_planner_db import INTERCEPT_CAPABLE, CAP_CAPABLE, CAS_CAPABLE, SEAD_CAPABLE -from gen.flights.flight import Flight, FlightType, FlightWaypoint +from gen.flights.flight import Flight, FlightType, FlightWaypoint, FlightWaypointType + + +def meter_to_feet(value_in_meter): + return int(3.28084 * value_in_meter) + + +def feet_to_meter(value_in_feet): + return int(float(value_in_feet)/3.048) + + +def meter_to_nm(value_in_meter): + return int(float(value_in_meter)*0.000539957) + + +def nm_to_meter(value_in_nm): + return int(float(value_in_nm)*1852) + # TODO : Ideally should be based on the aircraft type instead / Availability of fuel STRIKE_MAX_RANGE = 1500000 @@ -19,11 +36,15 @@ CAS_EVERY_X_MINUTES = 30 SEAD_EVERY_X_MINUTES = 40 STRIKE_EVERY_X_MINUTES = 40 -INGRESS_EGRESS_DISTANCE = 45000 -INGRESS_ALT = 6096 # 20k feet -EGRESS_ALT = 6096 # 20k feet -PATROL_ALT_RANGE = (3600, 9200) +INGRESS_EGRESS_DISTANCE = nm_to_meter(45) +INGRESS_ALT = feet_to_meter(20000) +EGRESS_ALT = feet_to_meter(20000) +PATROL_ALT_RANGE = (feet_to_meter(15000), feet_to_meter(33000)) NAV_ALT = 9144 +PATTERN_ALTITUDE = feet_to_meter(5000) + +CAP_DEFAULT_ENGAGE_DISTANCE = nm_to_meter(40) + class FlightPlanner: @@ -69,7 +90,7 @@ class FlightPlanner: self.commision_strike() - # TODO : commision STRIKE / ANTISHIP + # TODO : commision ANTISHIP def remove_flight(self, index): try: @@ -135,30 +156,81 @@ class FlightPlanner: ftype = FlightType.BARCAP if self.from_cp.is_carrier else FlightType.CAP flight = Flight(unit, 2, self.from_cp, ftype) - # Flight path : fly over each ground object (TODO : improve) flight.points = [] flight.scheduled_in = offset + i*random.randint(CAP_EVERY_X_MINUTES-5, CAP_EVERY_X_MINUTES+5) patrol_alt = random.randint(PATROL_ALT_RANGE[0], PATROL_ALT_RANGE[1]) - patrolled = [] - for ground_object in self.from_cp.ground_objects: - if ground_object.group_id not in patrolled and not ground_object.airbase_group: - point = FlightWaypoint(ground_object.position.x, ground_object.position.y, patrol_alt) - point.name = "Patrol point" - point.description = "Patrol #" + str(len(flight.points)) - point.pretty_name = "Patrol #" + str(len(flight.points)) - flight.points.append(point) - patrolled.append(ground_object.group_id) + # Choose a location for CAP patrols (Either behind frontline, or to protect ground objects) + rng = random.randint(0,100) + if rng < 80 and len(self._get_cas_locations()) > 0: + loc = random.choice(self._get_cas_locations()) + ingress, heading, distance = Conflict.frontline_vector(self.from_cp, loc, self.game.theater) + center = ingress.point_from_heading(heading, distance / 2) + orbit_center = center.point_from_heading(heading - 90, random.randint(nm_to_meter(6), nm_to_meter(15))) + radius = distance * 2 + orbit0p = orbit_center.point_from_heading(heading, radius) + orbit1p = orbit_center.point_from_heading(heading + 180, radius) + elif len(self.from_cp.ground_objects) > 0: + loc = random.choice(self.from_cp.ground_objects) + hdg = self.from_cp.position.heading_between_point(loc.position) + radius = random.randint(nm_to_meter(5), nm_to_meter(10)) + orbit0p = loc.position.point_from_heading(hdg - 90, radius) + orbit1p = loc.position.point_from_heading(hdg + 90, radius) + else: + loc = self.from_cp.position.point_from_heading(random.randint(0, 360), random.randint(nm_to_meter(5), nm_to_meter(40))) + hdg = self.from_cp.position.heading_between_point(loc.position) + radius = random.randint(nm_to_meter(40), nm_to_meter(120)) + orbit0p = loc.position.point_from_heading(hdg - 90, radius) + orbit1p = loc.position.point_from_heading(hdg + 90, radius) - if len(flight.points) == 0: - for i in range(3): - pos = self.from_cp.position.point_from_heading(random.randint(0, 360), random.randint(30000, 80000)) - point = FlightWaypoint(pos.x, pos.y, patrol_alt) - point.name = "Patrol point" - point.description = "Patrol #" + str(len(flight.points)) - point.pretty_name = "Patrol #" + str(len(flight.points)) - flight.points.append(point) + + # Create points + ascend_heading = random.randint(0, 360) + pos_ascend = self.from_cp.position.point_from_heading(ascend_heading, 30000) + ascend = FlightWaypoint(pos_ascend.x, pos_ascend.y, patrol_alt) + ascend.name = "ASCEND" + ascend.description = "Ascend to alt [" + str(meter_to_feet(patrol_alt)) + " ft]" + ascend.pretty_name = "Ascend to alt [" + str(meter_to_feet(patrol_alt)) + " ft]" + ascend.waypoint_type = FlightWaypointType.ASCEND_POINT + flight.points.append(ascend) + + orbit0 = FlightWaypoint(orbit0p.x, orbit0p.y, patrol_alt) + orbit0.name = "ORBIT 0" + orbit0.description = "Standby between this point and the next one" + orbit0.pretty_name = "Orbit race-track start" + orbit0.waypoint_type = FlightWaypointType.PATROL_TRACK + flight.points.append(orbit0) + + orbit1 = FlightWaypoint(orbit1p.x, orbit1p.y, patrol_alt) + orbit1.name = "ORBIT 1" + orbit1.description = "Standby between this point and the previous one" + orbit1.pretty_name = "Orbit race-track end" + orbit1.waypoint_type = FlightWaypointType.PATROL + flight.points.append(orbit1) + + orbit0.targets.append(self.from_cp) + obj_added = [] + for ground_object in self.from_cp.ground_objects: + if ground_object.obj_name not in obj_added and not ground_object.airbase_group: + orbit0.targets.append(ground_object) + obj_added.append(ground_object.obj_name) + + descend = self.from_cp.position.point_from_heading(ascend_heading-180, 30000) + descend = FlightWaypoint(descend.x, descend.y, PATTERN_ALTITUDE) + descend.name = "DESCEND" + descend.description = "Descend to pattern alt [5000ft]" + descend.pretty_name = "Descend to pattern alt [5000ft]" + descend.waypoint_type = FlightWaypointType.DESCENT_POINT + flight.points.append(descend) + + rtb = self.from_cp.position.point_from_heading(ascend_heading - 180, 30000) + rtb = FlightWaypoint(rtb.x, rtb.y, PATTERN_ALTITUDE) + rtb.name = "LANDING" + rtb.description = "RTB" + rtb.pretty_name = "RTB" + rtb.waypoint_type = FlightWaypointType.LANDING_POINT + flight.points.append(rtb) self.cap_flights.append(flight) self.flights.append(flight) @@ -203,18 +275,21 @@ class FlightPlanner: ingress_point.name = "INGRESS" ingress_point.pretty_name = "INGRESS" ingress_point.description = "Ingress into CAS area" + ingress_point.waypoint_type = FlightWaypointType.INGRESS_CAS flight.points.append(ingress_point) center_point = FlightWaypoint(center.x, center.y, 1000) center_point.description = "Provide CAS" center_point.name = "CAS" center_point.pretty_name = "INGRESS" + center_point.waypoint_type = FlightWaypointType.CAS flight.points.append(center_point) egress_point = FlightWaypoint(egress.x, egress.y, 1000) egress_point.description = "Egress from CAS area" egress_point.name = "EGRESS" egress_point.pretty_name = "EGRESS" + egress_point.waypoint_type = FlightWaypointType.EGRESS flight.points.append(egress_point) self.cas_flights.append(flight) @@ -262,23 +337,27 @@ class FlightPlanner: ingress_point = FlightWaypoint(ingress_pos.x, ingress_pos.y, INGRESS_ALT) ingress_point.pretty_name = "INGRESS on " + location.obj_name ingress_point.description = "INGRESS on " + location.obj_name + ingress_point.waypoint_type = FlightWaypointType.INGRESS_SEAD flight.points.append(ingress_point) - point = FlightWaypoint(location.position.x, location.position.y, 1000) + point = FlightWaypoint(location.position.x, location.position.y, 0) if flight.flight_type == FlightType.DEAD: point.description = "SEAD on " + location.obj_name point.pretty_name = "SEAD on " + location.obj_name + point.only_for_player = True else: point.description = "DEAD on " + location.obj_name point.pretty_name = "DEAD on " + location.obj_name + point.only_for_player = True - point.targets.append(location) + ingress_point.targets.append(location) flight.points.append(point) egress_pos = location.position.point_from_heading(egress_heading, INGRESS_EGRESS_DISTANCE) egress_point = FlightWaypoint(egress_pos.x, egress_pos.y, EGRESS_ALT) egress_point.pretty_name = "EGRESS on " + location.obj_name egress_point.description = "EGRESS on " + location.obj_name + egress_point.waypoint_type = FlightWaypointType.EGRESS flight.points.append(egress_point) self.sead_flights.append(flight) diff --git a/gen/flights/flight.py b/gen/flights/flight.py index 0bfad12a..84bd5c32 100644 --- a/gen/flights/flight.py +++ b/gen/flights/flight.py @@ -30,6 +30,24 @@ class FlightType(Enum): EWAR = 16 +class FlightWaypointType(Enum): + TAKEOFF = 0 # Take off point + ASCEND_POINT = 1 # Ascension point after take off + PATROL = 2 # Patrol point + PATROL_TRACK = 3 # Patrol race track + NAV = 4 # Nav point + INGRESS_STRIKE = 5 # Ingress strike (For generator, means that this should have bombing on next TARGET_POINT points) + INGRESS_SEAD = 6 # Ingress sead (For generator, means that this should attack groups on TARGET_GROUP_LOC points) + INGRESS_CAS = 7 # Ingress cas (should start CAS task) + CAS = 8 # Should do CAS there + EGRESS = 9 # Should stop attack + DESCENT_POINT = 10 # Should start descending to pattern alt + LANDING_POINT = 11 # Should land there + TARGET_POINT = 12 # A target building or static object, position + TARGET_GROUP_LOC = 13 # A target group approximate location + TARGET_SHIP = 14 # A target ship known location + + class FlightWaypoint: def __init__(self, x: float, y: float, alt=0): @@ -41,6 +59,8 @@ class FlightWaypoint: self.targets = [] self.obj_name = "" self.pretty_name = "" + self.waypoint_type = FlightWaypointType.TAKEOFF # type: FlightWaypointType + self.only_for_player = False class Flight: diff --git a/requirements.txt b/requirements.txt index ae4ea2f2..5fde471e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ pydcs>=0.9.4 Pyside2>=5.13.0 pyinstaller==3.5 +pyproj==2.6.1.post1 diff --git a/resources/customized_payloads/Su-24M.lua b/resources/customized_payloads/Su-24M.lua index a3f81aa9..0c11a702 100644 --- a/resources/customized_payloads/Su-24M.lua +++ b/resources/customized_payloads/Su-24M.lua @@ -2,156 +2,150 @@ local unitPayloads = { ["name"] = "Su-24M", ["payloads"] = { [1] = { - ["name"] = "ANTISHIP", - ["pylons"] = { - [1] = { - ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{D8F2C90B-887B-4B9E-9FE2-996BC9E9AF03}", - ["num"] = 2, - }, - [3] = { - ["CLSID"] = "{0519A264-0AB6-11d6-9193-00A0249B6F00}", - ["num"] = 5, - }, - [4] = { - ["CLSID"] = "{D8F2C90B-887B-4B9E-9FE2-996BC9E9AF03}", - ["num"] = 7, - }, - [5] = { - ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", - ["num"] = 8, - }, - }, - ["tasks"] = { - [1] = 29, - [2] = 30, - }, - }, - [2] = { - ["name"] = "CAS", - ["pylons"] = { - [1] = { - ["CLSID"] = "{292960BB-6518-41AC-BADA-210D65D5073C}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{292960BB-6518-41AC-BADA-210D65D5073C}", - ["num"] = 2, - }, - [3] = { - ["CLSID"] = "{292960BB-6518-41AC-BADA-210D65D5073C}", - ["num"] = 7, - }, - [4] = { - ["CLSID"] = "{292960BB-6518-41AC-BADA-210D65D5073C}", - ["num"] = 8, - }, - [5] = { - ["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}", - ["num"] = 6, - }, - [6] = { - ["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}", - ["num"] = 3, - }, - [7] = { - ["CLSID"] = "{3C612111-C7AD-476E-8A8E-2485812F4E5C}", - ["num"] = 4, - }, - [8] = { - ["CLSID"] = "{3C612111-C7AD-476E-8A8E-2485812F4E5C}", - ["num"] = 5, - }, - }, - ["tasks"] = { - [1] = 31, - }, - }, - [3] = { - ["name"] = "STRIKE", - ["pylons"] = { - [1] = { - ["CLSID"] = "{4203753F-8198-4E85-9924-6F8FF679F9FF}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{4203753F-8198-4E85-9924-6F8FF679F9FF}", - ["num"] = 2, - }, - [3] = { - ["CLSID"] = "{4203753F-8198-4E85-9924-6F8FF679F9FF}", - ["num"] = 3, - }, - [4] = { - ["CLSID"] = "{4203753F-8198-4E85-9924-6F8FF679F9FF}", - ["num"] = 4, - }, - [5] = { - ["CLSID"] = "{4203753F-8198-4E85-9924-6F8FF679F9FF}", - ["num"] = 5, - }, - [6] = { - ["CLSID"] = "{4203753F-8198-4E85-9924-6F8FF679F9FF}", - ["num"] = 6, - }, - [7] = { - ["CLSID"] = "{4203753F-8198-4E85-9924-6F8FF679F9FF}", - ["num"] = 7, - }, - [8] = { - ["CLSID"] = "{4203753F-8198-4E85-9924-6F8FF679F9FF}", - ["num"] = 8, - }, - }, - ["tasks"] = { - [1] = 31, - }, - }, - [4] = { ["name"] = "SEAD", ["pylons"] = { [1] = { - ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", - ["num"] = 1, - }, - [2] = { - ["CLSID"] = "{FE382A68-8620-4AC0-BDF5-709BFE3977D7}", - ["num"] = 2, - }, - [3] = { - ["CLSID"] = "{0519A264-0AB6-11d6-9193-00A0249B6F00}", - ["num"] = 5, - }, - [4] = { ["CLSID"] = "{FE382A68-8620-4AC0-BDF5-709BFE3977D7}", ["num"] = 7, }, - [5] = { - ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + [2] = { + ["CLSID"] = "{E86C5AA5-6D49-4F00-AD2E-79A62D6DDE26}", ["num"] = 8, }, + [3] = { + ["CLSID"] = "{E86C5AA5-6D49-4F00-AD2E-79A62D6DDE26}", + ["num"] = 1, + }, + [4] = { + ["CLSID"] = "{FE382A68-8620-4AC0-BDF5-709BFE3977D7}", + ["num"] = 2, + }, }, ["tasks"] = { - [1] = 29, }, }, - [5] = { + [2] = { + ["name"] = "STRIKE", + ["pylons"] = { + [1] = { + ["CLSID"] = "{KAB_1500LG_LOADOUT}", + ["num"] = 7, + }, + [2] = { + ["CLSID"] = "{3C612111-C7AD-476E-8A8E-2485812F4E5C}", + ["num"] = 8, + }, + [3] = { + ["CLSID"] = "{3C612111-C7AD-476E-8A8E-2485812F4E5C}", + ["num"] = 1, + }, + [4] = { + ["CLSID"] = "{KAB_1500LG_LOADOUT}", + ["num"] = 2, + }, + [5] = { + ["CLSID"] = "{E2C426E3-8B10-4E09-B733-9CDC26520F48}", + ["num"] = 3, + }, + [6] = { + ["CLSID"] = "{E2C426E3-8B10-4E09-B733-9CDC26520F48}", + ["num"] = 6, + }, + [7] = { + ["CLSID"] = "{3C612111-C7AD-476E-8A8E-2485812F4E5C}", + ["num"] = 4, + }, + [8] = { + ["CLSID"] = "{3C612111-C7AD-476E-8A8E-2485812F4E5C}", + ["num"] = 5, + }, + }, + ["tasks"] = { + }, + }, + [3] = { ["name"] = "CAP", ["pylons"] = { [1] = { - ["CLSID"] = "{B0DBC591-0F52-4F7D-AD7B-51E67725FB81}", - ["num"] = 1, + ["CLSID"] = "{7D7EC917-05F6-49D4-8045-61FC587DD019}", + ["num"] = 7, }, [2] = { ["CLSID"] = "{275A2855-4A79-4B2D-B082-91EA2ADF4691}", ["num"] = 8, }, + [3] = { + ["CLSID"] = "{B0DBC591-0F52-4F7D-AD7B-51E67725FB81}", + ["num"] = 1, + }, + [4] = { + ["CLSID"] = "{7D7EC917-05F6-49D4-8045-61FC587DD019}", + ["num"] = 2, + }, + }, + ["tasks"] = { + }, + }, + [4] = { + ["name"] = "ANTISHIP", + ["pylons"] = { + [1] = { + ["CLSID"] = "{D8F2C90B-887B-4B9E-9FE2-996BC9E9AF03}", + ["num"] = 7, + }, + [2] = { + ["CLSID"] = "{E86C5AA5-6D49-4F00-AD2E-79A62D6DDE26}", + ["num"] = 8, + }, + [3] = { + ["CLSID"] = "{E86C5AA5-6D49-4F00-AD2E-79A62D6DDE26}", + ["num"] = 1, + }, + [4] = { + ["CLSID"] = "{D8F2C90B-887B-4B9E-9FE2-996BC9E9AF03}", + ["num"] = 2, + }, + }, + ["tasks"] = { + }, + }, + [5] = { + ["name"] = "CAS", + ["pylons"] = { + [1] = { + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + ["num"] = 8, + }, + [2] = { + ["CLSID"] = "{6DADF342-D4BA-4D8A-B081-BA928C4AF86D}", + ["num"] = 1, + }, + [3] = { + ["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}", + ["num"] = 2, + }, + [4] = { + ["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}", + ["num"] = 7, + }, + [5] = { + ["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}", + ["num"] = 6, + }, + [6] = { + ["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}", + ["num"] = 3, + }, + [7] = { + ["CLSID"] = "{3C612111-C7AD-476E-8A8E-2485812F4E5C}", + ["num"] = 5, + }, + [8] = { + ["CLSID"] = "{3C612111-C7AD-476E-8A8E-2485812F4E5C}", + ["num"] = 4, + }, }, ["tasks"] = { - [1] = 32, }, }, }, diff --git a/theater/controlpoint.py b/theater/controlpoint.py index 1bead07d..28431f02 100644 --- a/theater/controlpoint.py +++ b/theater/controlpoint.py @@ -38,6 +38,7 @@ class ControlPoint: cptype: ControlPointType = None ICLS_counter = 1 + alt = 0 def __init__(self, id: int, name: str, position: Point, at, radials: typing.Collection[int], size: int, importance: float, has_frontline=True, cptype=ControlPointType.AIRBASE):