mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Flight Planner first version (just print planned flight in log but does not generate them yet)
This commit is contained in:
parent
fa99df3ce7
commit
b7ee98dcd6
11
game/game.py
11
game/game.py
@ -8,6 +8,7 @@ from dcs.vehicles import *
|
|||||||
|
|
||||||
from game.game_stats import GameStats
|
from game.game_stats import GameStats
|
||||||
from gen.conflictgen import Conflict
|
from gen.conflictgen import Conflict
|
||||||
|
from gen.flights.ai_flight_planner import FlightPlanner
|
||||||
from userdata.debriefing import Debriefing
|
from userdata.debriefing import Debriefing
|
||||||
from theater import *
|
from theater import *
|
||||||
|
|
||||||
@ -111,6 +112,7 @@ class Game:
|
|||||||
self.date = datetime(start_date.year, start_date.month, start_date.day)
|
self.date = datetime(start_date.year, start_date.month, start_date.day)
|
||||||
self.game_stats = GameStats()
|
self.game_stats = GameStats()
|
||||||
self.game_stats.update(self)
|
self.game_stats.update(self)
|
||||||
|
self.planners = {}
|
||||||
|
|
||||||
def _roll(self, prob, mult):
|
def _roll(self, prob, mult):
|
||||||
if self.settings.version == "dev":
|
if self.settings.version == "dev":
|
||||||
@ -310,6 +312,15 @@ class Game:
|
|||||||
# Update statistics
|
# Update statistics
|
||||||
self.game_stats.update(self)
|
self.game_stats.update(self)
|
||||||
|
|
||||||
|
# Plan flights for next turn
|
||||||
|
self.planners = {}
|
||||||
|
for cp in self.theater.controlpoints:
|
||||||
|
planner = FlightPlanner(cp, self)
|
||||||
|
planner.plan_flights()
|
||||||
|
self.planners[cp.id] = planner
|
||||||
|
print(planner)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_turn_daytime(self):
|
def current_turn_daytime(self):
|
||||||
return ["dawn", "day", "dusk", "night"][self.turn % 4]
|
return ["dawn", "day", "dusk", "night"][self.turn % 4]
|
||||||
|
|||||||
@ -135,10 +135,9 @@ class Operation:
|
|||||||
# Generate ground object first
|
# Generate ground object first
|
||||||
self.groundobjectgen.generate()
|
self.groundobjectgen.generate()
|
||||||
|
|
||||||
# air support
|
# Air Support (Tanker & Awacs)
|
||||||
self.airsupportgen.generate(self.is_awacs_enabled)
|
self.airsupportgen.generate(self.is_awacs_enabled)
|
||||||
|
|
||||||
|
|
||||||
# Generate Activity on the map
|
# Generate Activity on the map
|
||||||
for cp in self.game.theater.controlpoints:
|
for cp in self.game.theater.controlpoints:
|
||||||
side = cp.captured
|
side = cp.captured
|
||||||
@ -157,20 +156,15 @@ class Operation:
|
|||||||
self.airgen.generate_dead_sead(cp, country)
|
self.airgen.generate_dead_sead(cp, country)
|
||||||
|
|
||||||
|
|
||||||
for i, tanker_type in enumerate(self.airsupportgen.generated_tankers):
|
|
||||||
self.briefinggen.append_frequency("Tanker {} ({})".format(TANKER_CALLSIGNS[i], tanker_type), "{}X/{} MHz AM".format(97+i, 130+i))
|
|
||||||
|
|
||||||
if self.is_awacs_enabled:
|
|
||||||
self.briefinggen.append_frequency("AWACS", "133 MHz AM")
|
|
||||||
|
|
||||||
# combined arms
|
#Setup combined arms parameters
|
||||||
self.current_mission.groundControl.pilot_can_control_vehicles = self.ca_slots > 0
|
self.current_mission.groundControl.pilot_can_control_vehicles = self.ca_slots > 0
|
||||||
if self.game.player_country in [country.name for country in self.current_mission.coalition["blue"].countries.values()]:
|
if self.game.player_country in [country.name for country in self.current_mission.coalition["blue"].countries.values()]:
|
||||||
self.current_mission.groundControl.blue_tactical_commander = self.ca_slots
|
self.current_mission.groundControl.blue_tactical_commander = self.ca_slots
|
||||||
else:
|
else:
|
||||||
self.current_mission.groundControl.red_tactical_commander = self.ca_slots
|
self.current_mission.groundControl.red_tactical_commander = self.ca_slots
|
||||||
|
|
||||||
#self.extra_aagen.generate()
|
|
||||||
|
|
||||||
# triggers
|
# triggers
|
||||||
if self.game.is_player_attack(self.conflict.attackers_country):
|
if self.game.is_player_attack(self.conflict.attackers_country):
|
||||||
@ -192,18 +186,10 @@ class Operation:
|
|||||||
# options
|
# options
|
||||||
self.forcedoptionsgen.generate()
|
self.forcedoptionsgen.generate()
|
||||||
|
|
||||||
# main frequencies
|
# Generate Visuals Smoke Effects
|
||||||
self.briefinggen.append_frequency("Flight", "251 MHz AM")
|
|
||||||
if self.departure_cp.is_global or self.conflict.to_cp.is_global:
|
|
||||||
self.briefinggen.append_frequency("Carrier", "20X/ICLS CHAN1")
|
|
||||||
|
|
||||||
# briefing
|
|
||||||
self.briefinggen.generate()
|
|
||||||
|
|
||||||
# visuals
|
|
||||||
self.visualgen.generate()
|
self.visualgen.generate()
|
||||||
|
|
||||||
# Scripts
|
# Inject Lua Scripts
|
||||||
load_mist = TriggerStart(comment="Load Mist Lua Framework")
|
load_mist = TriggerStart(comment="Load Mist Lua Framework")
|
||||||
with open(os.path.abspath("./resources/scripts/mist_4_3_74.lua")) as f:
|
with open(os.path.abspath("./resources/scripts/mist_4_3_74.lua")) as f:
|
||||||
load_mist.add_action(DoScript(String(f.read())))
|
load_mist.add_action(DoScript(String(f.read())))
|
||||||
@ -219,5 +205,19 @@ class Operation:
|
|||||||
load_dcs_libe.add_action(DoScript(String(script)))
|
load_dcs_libe.add_action(DoScript(String(script)))
|
||||||
self.current_mission.triggerrules.triggers.append(load_dcs_libe)
|
self.current_mission.triggerrules.triggers.append(load_dcs_libe)
|
||||||
|
|
||||||
|
# Briefing Generation
|
||||||
|
for i, tanker_type in enumerate(self.airsupportgen.generated_tankers):
|
||||||
|
self.briefinggen.append_frequency("Tanker {} ({})".format(TANKER_CALLSIGNS[i], tanker_type), "{}X/{} MHz AM".format(97+i, 130+i))
|
||||||
|
|
||||||
|
if self.is_awacs_enabled:
|
||||||
|
self.briefinggen.append_frequency("AWACS", "133 MHz AM")
|
||||||
|
|
||||||
|
self.briefinggen.append_frequency("Flight", "251 MHz AM")
|
||||||
|
if self.departure_cp.is_global or self.conflict.to_cp.is_global:
|
||||||
|
self.briefinggen.append_frequency("Carrier", "20X/ICLS CHAN1")
|
||||||
|
|
||||||
|
# Generate the briefing
|
||||||
|
self.briefinggen.generate()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
209
gen/flights/ai_flight_planner.py
Normal file
209
gen/flights/ai_flight_planner.py
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
import math
|
||||||
|
import operator
|
||||||
|
import typing
|
||||||
|
import random
|
||||||
|
|
||||||
|
from gen.flights.ai_flight_planner_db import INTERCEPT_CAPABLE, CAP_CAPABLE, CAS_CAPABLE
|
||||||
|
from gen.flights.flight import Flight, FlightType
|
||||||
|
|
||||||
|
|
||||||
|
# TODO : Ideally should be based on the aircraft type instead / Availability of fuel
|
||||||
|
STRIKE_MAX_RANGE = 30000
|
||||||
|
SEAD_MAX_RANGE = 30000
|
||||||
|
|
||||||
|
MAX_NUMBER_OF_INTERCEPTION_GROUP = 3
|
||||||
|
MISSION_DURATION = 120 # in minutes
|
||||||
|
CAP_EVERY_X_MINUTES = 20
|
||||||
|
|
||||||
|
|
||||||
|
class FlightPlanner:
|
||||||
|
|
||||||
|
from_cp = None
|
||||||
|
game = None
|
||||||
|
|
||||||
|
interceptor_flights = []
|
||||||
|
cap_flights = []
|
||||||
|
cas_flights = []
|
||||||
|
strike_flights = []
|
||||||
|
sead_flights = []
|
||||||
|
flights = []
|
||||||
|
|
||||||
|
def __init__(self, from_cp, game):
|
||||||
|
# TODO : have the flight planner depend on a 'stance' setting : [Defensive, Aggresive... etc] and faction doctrine
|
||||||
|
self.from_cp = from_cp
|
||||||
|
self.game = game
|
||||||
|
self.aircraft_inventory = {} # local copy of the airbase inventory
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""
|
||||||
|
Reset the planned flights and avaialble units
|
||||||
|
"""
|
||||||
|
self.aircraft_inventory = dict({k: v for k, v in self.from_cp.base.aircraft.items()})
|
||||||
|
self.interceptor_flights = []
|
||||||
|
self.cap_flights = []
|
||||||
|
self.cas_flights = []
|
||||||
|
self.strike_flights = []
|
||||||
|
self.sead_flights = []
|
||||||
|
self.flights = []
|
||||||
|
|
||||||
|
def plan_flights(self):
|
||||||
|
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
# The priority is to assign air-superiority fighter or interceptor to interception roles, so they can scramble if there is an attacker
|
||||||
|
self.commision_interceptors()
|
||||||
|
|
||||||
|
# Then some CAP patrol for the next 2 hours
|
||||||
|
self.commision_barcap()
|
||||||
|
|
||||||
|
# TODO : commision CAS / BAI
|
||||||
|
|
||||||
|
# TODO : commision SEAD
|
||||||
|
|
||||||
|
# TODO : commision STRIKE / ANTISHIP
|
||||||
|
|
||||||
|
def commision_interceptors(self):
|
||||||
|
"""
|
||||||
|
Pick some aircraft to assign them to interception roles
|
||||||
|
"""
|
||||||
|
|
||||||
|
# At least try to generate one interceptor group
|
||||||
|
number_of_interceptor_groups = min(max(sum([v for k, v in self.aircraft_inventory.items()]) / 4, MAX_NUMBER_OF_INTERCEPTION_GROUP), 1)
|
||||||
|
possible_interceptors = [k for k in self.aircraft_inventory.keys() if k in INTERCEPT_CAPABLE]
|
||||||
|
|
||||||
|
if len(possible_interceptors) <= 0:
|
||||||
|
possible_interceptors = [k for k,v in self.aircraft_inventory.items() if k in CAP_CAPABLE and v >= 2]
|
||||||
|
|
||||||
|
if number_of_interceptor_groups > 0:
|
||||||
|
inventory = dict({k: v for k, v in self.aircraft_inventory.items() if k in possible_interceptors})
|
||||||
|
for i in range(number_of_interceptor_groups):
|
||||||
|
try:
|
||||||
|
unit = random.choice([k for k,v in inventory.items() if v >= 2])
|
||||||
|
except IndexError:
|
||||||
|
break
|
||||||
|
inventory[unit] = inventory[unit] - 2
|
||||||
|
flight = Flight(unit, 2, self.from_cp, FlightType.INTERCEPTION)
|
||||||
|
flight.points = []
|
||||||
|
|
||||||
|
self.interceptor_flights.append(flight)
|
||||||
|
self.flights.append(flight)
|
||||||
|
|
||||||
|
# Update inventory
|
||||||
|
for k, v in inventory.items():
|
||||||
|
self.aircraft_inventory[k] = v
|
||||||
|
|
||||||
|
def commision_barcap(self):
|
||||||
|
"""
|
||||||
|
Pick some aircraft to assign them to defensive CAP roles (BARCAP)
|
||||||
|
"""
|
||||||
|
|
||||||
|
possible_aircraft = [k for k, v in self.aircraft_inventory.items() if k in CAP_CAPABLE and v >= 2]
|
||||||
|
inventory = dict({k: v for k, v in self.aircraft_inventory.items() if k in possible_aircraft})
|
||||||
|
|
||||||
|
offset = random.randint(0,5)
|
||||||
|
for i in range(int(MISSION_DURATION/CAP_EVERY_X_MINUTES)):
|
||||||
|
|
||||||
|
try:
|
||||||
|
unit = random.choice([k for k, v in inventory.items() if v >= 2])
|
||||||
|
except IndexError:
|
||||||
|
break
|
||||||
|
|
||||||
|
inventory[unit] = inventory[unit] - 2
|
||||||
|
flight = Flight(unit, 2, self.from_cp, FlightType.BARCAP)
|
||||||
|
|
||||||
|
# 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(3600, 7000)
|
||||||
|
|
||||||
|
patrolled = []
|
||||||
|
for ground_object in self.from_cp.ground_objects:
|
||||||
|
if ground_object.group_id not in patrolled and not ground_object.airbase_group:
|
||||||
|
flight.points.append([ground_object.position.x, ground_object.position.y, patrol_alt])
|
||||||
|
patrolled.append(ground_object.group_id)
|
||||||
|
|
||||||
|
self.cap_flights.append(flight)
|
||||||
|
self.flights.append(flight)
|
||||||
|
|
||||||
|
# Update inventory
|
||||||
|
for k, v in inventory.items():
|
||||||
|
self.aircraft_inventory[k] = v
|
||||||
|
|
||||||
|
def _get_strike_targets_in_range(self):
|
||||||
|
"""
|
||||||
|
@return a list of potential strike targets in range
|
||||||
|
"""
|
||||||
|
|
||||||
|
# target, distance
|
||||||
|
potential_targets = []
|
||||||
|
|
||||||
|
for cp in [c for c in self.game.theater.controlpoints if c.captured != self.from_cp.captured]:
|
||||||
|
|
||||||
|
# Compute distance to current cp
|
||||||
|
distance = math.hypot(cp.position.x - self.from_cp.position.x,
|
||||||
|
cp.position.y - self.from_cp.position.y)
|
||||||
|
|
||||||
|
if distance > 2*STRIKE_MAX_RANGE:
|
||||||
|
# Then it's unlikely any child ground object is in range
|
||||||
|
return
|
||||||
|
|
||||||
|
added_group = []
|
||||||
|
for g in cp.ground_objects:
|
||||||
|
if g.group_id in added_group: continue
|
||||||
|
|
||||||
|
# Compute distance to current cp
|
||||||
|
distance = math.hypot(cp.position.x - self.from_cp.position.x,
|
||||||
|
cp.position.y - self.from_cp.position.y)
|
||||||
|
|
||||||
|
if distance < SEAD_MAX_RANGE:
|
||||||
|
potential_targets.append((g, distance))
|
||||||
|
added_group.append(g)
|
||||||
|
|
||||||
|
return potential_targets.sort(key=operator.itemgetter(1))
|
||||||
|
|
||||||
|
def _get_sead_targets_in_range(self):
|
||||||
|
"""
|
||||||
|
@return a list of potential sead targets in range
|
||||||
|
"""
|
||||||
|
|
||||||
|
# target, distance
|
||||||
|
potential_targets = []
|
||||||
|
|
||||||
|
for cp in [c for c in self.game.theater.controlpoints if c.captured != self.from_cp.captured]:
|
||||||
|
|
||||||
|
# Compute distance to current cp
|
||||||
|
distance = math.hypot(cp.position.x - self.from_cp.position.x,
|
||||||
|
cp.position.y - self.from_cp.position.y)
|
||||||
|
|
||||||
|
# Then it's unlikely any ground object is range
|
||||||
|
if distance > 2*SEAD_MAX_RANGE:
|
||||||
|
return
|
||||||
|
|
||||||
|
for g in cp.ground_objects:
|
||||||
|
|
||||||
|
if g.dcs_identifier == "AA":
|
||||||
|
|
||||||
|
# Check that there is at least one unit with a radar in the ground objects unit groups
|
||||||
|
number_of_units = sum([len([r for r in group.units if hasattr(r, "detection_range") and r.detection_range > 1000]) for group in g.groups])
|
||||||
|
if number_of_units <= 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Compute distance to current cp
|
||||||
|
distance = math.hypot(cp.position.x - self.from_cp.position.x,
|
||||||
|
cp.position.y - self.from_cp.position.y)
|
||||||
|
|
||||||
|
if distance < SEAD_MAX_RANGE:
|
||||||
|
potential_targets.append((g, distance))
|
||||||
|
|
||||||
|
return potential_targets.sort(key=operator.itemgetter(1))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "-"*40 + "\n" + self.from_cp.name + " planned flights :\n"\
|
||||||
|
+ "-"*40 + "\n" + "\n".join([repr(f) for f in self.flights]) + "\n" + "-"*40
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
177
gen/flights/ai_flight_planner_db.py
Normal file
177
gen/flights/ai_flight_planner_db.py
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
from dcs.planes import *
|
||||||
|
from dcs.helicopters import *
|
||||||
|
|
||||||
|
# Interceptor are the aircraft prioritized for interception tasks
|
||||||
|
# If none is available, the AI will use regular CAP-capable aircraft instead
|
||||||
|
INTERCEPT_CAPABLE = [
|
||||||
|
MiG_21Bis,
|
||||||
|
MiG_25PD,
|
||||||
|
MiG_31,
|
||||||
|
|
||||||
|
M_2000C,
|
||||||
|
Mirage_2000_5,
|
||||||
|
|
||||||
|
F_14B,
|
||||||
|
F_15C,
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
# Used for CAP, Escort, and intercept if there is not a specialised aircraft available
|
||||||
|
CAP_CAPABLE = [
|
||||||
|
MiG_15bis,
|
||||||
|
MiG_19P,
|
||||||
|
MiG_21Bis,
|
||||||
|
MiG_23MLD,
|
||||||
|
MiG_29A,
|
||||||
|
MiG_29G,
|
||||||
|
MiG_29S,
|
||||||
|
|
||||||
|
Su_27,
|
||||||
|
J_11A,
|
||||||
|
Su_30,
|
||||||
|
Su_33,
|
||||||
|
|
||||||
|
M_2000C,
|
||||||
|
Mirage_2000_5,
|
||||||
|
|
||||||
|
F_86F_Sabre,
|
||||||
|
F_4E,
|
||||||
|
F_5E_3,
|
||||||
|
F_14B,
|
||||||
|
F_15C,
|
||||||
|
F_16C_50,
|
||||||
|
FA_18C_hornet,
|
||||||
|
|
||||||
|
C_101CC,
|
||||||
|
L_39ZA,
|
||||||
|
|
||||||
|
P_51D_30_NA,
|
||||||
|
P_51D,
|
||||||
|
|
||||||
|
SpitfireLFMkIXCW,
|
||||||
|
SpitfireLFMkIX,
|
||||||
|
|
||||||
|
Bf_109K_4,
|
||||||
|
FW_190D9,
|
||||||
|
FW_190A8,
|
||||||
|
]
|
||||||
|
|
||||||
|
# USed for CAS (Close air support) and BAI (Battlefield Interdiction)
|
||||||
|
CAS_CAPABLE = [
|
||||||
|
|
||||||
|
MiG_15bis,
|
||||||
|
MiG_29A,
|
||||||
|
MiG_27K,
|
||||||
|
MiG_29S,
|
||||||
|
|
||||||
|
Su_17M4,
|
||||||
|
Su_24M,
|
||||||
|
Su_24MR,
|
||||||
|
Su_25,
|
||||||
|
Su_25T,
|
||||||
|
Su_34,
|
||||||
|
|
||||||
|
M_2000C,
|
||||||
|
|
||||||
|
A_10A,
|
||||||
|
A_10C,
|
||||||
|
AV8BNA,
|
||||||
|
|
||||||
|
F_86F_Sabre,
|
||||||
|
F_5E_3,
|
||||||
|
F_14B,
|
||||||
|
F_16C_50,
|
||||||
|
FA_18C_hornet,
|
||||||
|
|
||||||
|
C_101CC,
|
||||||
|
L_39ZA,
|
||||||
|
AJS37,
|
||||||
|
|
||||||
|
SA342M,
|
||||||
|
SA342L,
|
||||||
|
|
||||||
|
AH_64A,
|
||||||
|
AH_64D,
|
||||||
|
|
||||||
|
UH_1H,
|
||||||
|
|
||||||
|
Mi_8MT,
|
||||||
|
Mi_28N,
|
||||||
|
Mi_24V,
|
||||||
|
Ka_50,
|
||||||
|
|
||||||
|
P_51D_30_NA,
|
||||||
|
P_51D,
|
||||||
|
|
||||||
|
SpitfireLFMkIXCW,
|
||||||
|
SpitfireLFMkIX,
|
||||||
|
|
||||||
|
Bf_109K_4,
|
||||||
|
FW_190D9,
|
||||||
|
FW_190A8,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Aircraft used for SEAD / DEAD tasks
|
||||||
|
SEAD_CAPABLE = [
|
||||||
|
F_4E,
|
||||||
|
FA_18C_hornet,
|
||||||
|
F_16C_50,
|
||||||
|
AV8BNA,
|
||||||
|
|
||||||
|
Su_24M,
|
||||||
|
Su_25T,
|
||||||
|
Su_25TM,
|
||||||
|
Su_17M4,
|
||||||
|
Su_30,
|
||||||
|
Su_34,
|
||||||
|
MiG_27K,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Aircraft used for Strike mission
|
||||||
|
STRIKE_CAPABLE = [
|
||||||
|
MiG_15bis,
|
||||||
|
MiG_29A,
|
||||||
|
MiG_27K,
|
||||||
|
MiG_29S,
|
||||||
|
|
||||||
|
Su_17M4,
|
||||||
|
Su_24M,
|
||||||
|
Su_24MR,
|
||||||
|
Su_25,
|
||||||
|
Su_25T,
|
||||||
|
Su_34,
|
||||||
|
|
||||||
|
M_2000C,
|
||||||
|
|
||||||
|
A_10A,
|
||||||
|
A_10C,
|
||||||
|
AV8BNA,
|
||||||
|
|
||||||
|
F_86F_Sabre,
|
||||||
|
F_5E_3,
|
||||||
|
F_14B,
|
||||||
|
F_16C_50,
|
||||||
|
FA_18C_hornet,
|
||||||
|
|
||||||
|
C_101CC,
|
||||||
|
L_39ZA,
|
||||||
|
AJS37,
|
||||||
|
|
||||||
|
M_2000C,
|
||||||
|
|
||||||
|
P_51D_30_NA,
|
||||||
|
P_51D,
|
||||||
|
|
||||||
|
SpitfireLFMkIXCW,
|
||||||
|
SpitfireLFMkIX,
|
||||||
|
|
||||||
|
Bf_109K_4,
|
||||||
|
FW_190D9,
|
||||||
|
FW_190A8,
|
||||||
|
]
|
||||||
|
|
||||||
|
ANTISHIP_CAPABLE = [
|
||||||
|
Su_24M,
|
||||||
|
F_A_18C,
|
||||||
|
AV8BNA,
|
||||||
|
]
|
||||||
56
gen/flights/flight.py
Normal file
56
gen/flights/flight.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
from dcs.unittype import UnitType
|
||||||
|
from enum import Enum
|
||||||
|
from game import db
|
||||||
|
|
||||||
|
|
||||||
|
class FlightType(Enum):
|
||||||
|
CAP = 0
|
||||||
|
TARCAP = 1
|
||||||
|
BARCAP = 2
|
||||||
|
CAS = 3
|
||||||
|
INTERCEPTION = 4
|
||||||
|
STRIKE = 5
|
||||||
|
ANTISHIP = 6
|
||||||
|
SEAD = 7
|
||||||
|
DEAD = 8
|
||||||
|
ESCORT = 9
|
||||||
|
BAI = 10
|
||||||
|
|
||||||
|
# Helos
|
||||||
|
TROOP_TRANSPORT = 11
|
||||||
|
LOGISTICS = 12
|
||||||
|
EVAC = 13
|
||||||
|
|
||||||
|
|
||||||
|
class Flight:
|
||||||
|
|
||||||
|
unit_type: UnitType
|
||||||
|
from_cp = None
|
||||||
|
points = []
|
||||||
|
type = ""
|
||||||
|
count = 0
|
||||||
|
client_count = 0
|
||||||
|
|
||||||
|
# How long before this flight should take off
|
||||||
|
scheduled_in = 0
|
||||||
|
|
||||||
|
def __init__(self, unit_type: UnitType, count: int, from_cp, flight_type: FlightType):
|
||||||
|
self.unit_type = unit_type
|
||||||
|
self.count = count
|
||||||
|
self.from_cp = from_cp
|
||||||
|
self.flight_type = flight_type
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.flight_type.name + " | " + str(self.count) + "x" + db.unit_type_name(self.unit_type)\
|
||||||
|
+ " in " + str(self.scheduled_in) + " minutes (" + str(len(self.points)) + " wpt)"
|
||||||
|
|
||||||
|
# Test
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
from dcs.planes import A_10C
|
||||||
|
from theater import ControlPoint, Point
|
||||||
|
|
||||||
|
from_cp = ControlPoint(0, "AA", Point(0,0), None, [], 0, 0)
|
||||||
|
f = Flight(A_10C, 4, from_cp, FlightType.CAS)
|
||||||
|
f.scheduled_in = 50
|
||||||
|
print(f)
|
||||||
BIN
resources/normandy.gif
Normal file
BIN
resources/normandy.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 369 KiB |
@ -1,8 +1,7 @@
|
|||||||
import typing
|
|
||||||
import re
|
import re
|
||||||
|
import typing
|
||||||
|
|
||||||
from dcs.mapping import *
|
from dcs.mapping import *
|
||||||
from dcs.country import *
|
|
||||||
from dcs.terrain import Airport
|
from dcs.terrain import Airport
|
||||||
|
|
||||||
from .theatergroundobject import TheaterGroundObject
|
from .theatergroundobject import TheaterGroundObject
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user