mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
base mission generation framework
This commit is contained in:
parent
6152570fd8
commit
f4a3aef2d5
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
__pycache__
|
__pycache__
|
||||||
|
output.miz
|
||||||
|
.DS_Store
|
||||||
|
|||||||
20
__init__.py
20
__init__.py
@ -4,22 +4,34 @@ import dcs
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import gen
|
import gen
|
||||||
|
import theater.caucasus
|
||||||
|
|
||||||
m = dcs.Mission()
|
m = dcs.Mission()
|
||||||
|
|
||||||
|
theater = theater.caucasus.CaucasusTheater()
|
||||||
|
conflict = theater.controlpoints[0].conflict_attack(theater.controlpoints[1], m.country("USA"), m.country("Russia"))
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
conflict = gen.Conflict(
|
conflict = gen.Conflict(
|
||||||
heading=100,
|
heading=100,
|
||||||
attacker=m.country("USA"),
|
attacker=m.country("USA"),
|
||||||
defender=m.country("Russia"),
|
defender=m.country("Russia"),
|
||||||
point=m.terrain.krymsk().position,
|
point=m.terrain.krymsk().position,
|
||||||
size=10000)
|
size=10000)
|
||||||
|
"""
|
||||||
|
|
||||||
armor_conflict = gen.ArmorConflictGenerator(m, conflict)
|
armor_conflict = gen.ArmorConflictGenerator(m, conflict)
|
||||||
armor_conflict.generate(
|
armor_conflict.generate(
|
||||||
attackers={dcs.vehicles.Armor.MBT_M1A2_Abrams: 8},
|
attackers={dcs.vehicles.Armor.MBT_M1A2_Abrams: 8},
|
||||||
defenders={dcs.vehicles.Armor.MBT_T_80U: 6})
|
defenders={dcs.vehicles.Armor.MBT_T_80U: 10})
|
||||||
|
|
||||||
aircraft_conflict = gen.AircraftConflictGenerator(m, conflict)
|
aircraft_conflict = gen.AircraftConflictGenerator(m, conflict)
|
||||||
aircraft_conflict.generate_cas({dcs.planes.A_10C: 2})
|
aircraft_conflict.generate_cas({dcs.planes.A_10C: 4})
|
||||||
aircraft_conflict.generate_escort({dcs.planes.F_15C: 2})
|
aircraft_conflict.generate_escort({dcs.planes.F_15C: 4})
|
||||||
aircraft_conflict.generate_interceptors({dcs.planes.Su_27: 2})
|
aircraft_conflict.generate_interceptors({dcs.planes.Su_27: 6})
|
||||||
|
|
||||||
|
aa_conflict = gen.AAConflictGenerator(m, conflict)
|
||||||
|
aa_conflict.generate({dcs.vehicles.AirDefence.AAA_ZU_23_on_Ural_375: 3})
|
||||||
|
|
||||||
|
m.save("output.miz")
|
||||||
|
|||||||
11
game/game.py
Normal file
11
game/game.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import typing
|
||||||
|
|
||||||
|
from theater.conflicttheater import *
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
def __init__(self, theater: ConflictTheater):
|
||||||
|
self.theater = theater
|
||||||
|
|
||||||
|
def pass_time(self, time: int):
|
||||||
|
pass
|
||||||
|
|
||||||
3
game/side.py
Normal file
3
game/side.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import typing
|
||||||
|
import dcs
|
||||||
|
|
||||||
40
gen/aaa.py
40
gen/aaa.py
@ -0,0 +1,40 @@
|
|||||||
|
import typing
|
||||||
|
import pdb
|
||||||
|
import dcs
|
||||||
|
|
||||||
|
from random import randint
|
||||||
|
|
||||||
|
import globals
|
||||||
|
|
||||||
|
from .conflictgen import *
|
||||||
|
from .naming import *
|
||||||
|
|
||||||
|
from dcs.mission import *
|
||||||
|
from dcs.vehicles import *
|
||||||
|
from dcs.unitgroup import *
|
||||||
|
from dcs.unittype import *
|
||||||
|
from dcs.mapping import *
|
||||||
|
from dcs.point import *
|
||||||
|
from dcs.task import *
|
||||||
|
|
||||||
|
DISTANCE_FACTOR = 4, 5
|
||||||
|
|
||||||
|
class AAConflictGenerator:
|
||||||
|
def __init__(self, mission: Mission, conflict: Conflict):
|
||||||
|
self.m = mission
|
||||||
|
self.conflict = conflict
|
||||||
|
|
||||||
|
def generate(self, units: typing.Dict[UnitType, int]):
|
||||||
|
for type, count in units.items():
|
||||||
|
for _ in range(count):
|
||||||
|
p = self.conflict.ground_defenders_location.random_point_within(
|
||||||
|
self.conflict.size * DISTANCE_FACTOR[1],
|
||||||
|
self.conflict.size * DISTANCE_FACTOR[0])
|
||||||
|
|
||||||
|
self.m.vehicle_group(
|
||||||
|
country=self.conflict.defenders_side,
|
||||||
|
name=namegen.next_ground_group_name(),
|
||||||
|
_type=type,
|
||||||
|
position=p,
|
||||||
|
group_size=1)
|
||||||
|
|
||||||
@ -17,14 +17,15 @@ from dcs.mapping import *
|
|||||||
from dcs.point import *
|
from dcs.point import *
|
||||||
from dcs.task import *
|
from dcs.task import *
|
||||||
|
|
||||||
SPREAD_DISTANCE_FACTOR = 0.1, 0.25
|
SPREAD_DISTANCE_FACTOR = 1, 2
|
||||||
SPREAD_DISTANCE_SIZE_FACTOR = 0.5
|
|
||||||
ESCORT_MAX_DIST = 30000
|
ESCORT_MAX_DIST = 30000
|
||||||
|
|
||||||
WARM_START_ALTITUDE = 6000
|
WARM_START_ALTITUDE = 6000
|
||||||
WARM_START_AIRSPEED = 300
|
WARM_START_AIRSPEED = 300
|
||||||
CAS_ALTITUDE = 3000
|
CAS_ALTITUDE = 3000
|
||||||
|
|
||||||
|
INTERCEPT_MAX_DISTANCE_FACTOR = 15
|
||||||
|
|
||||||
class AircraftConflictGenerator:
|
class AircraftConflictGenerator:
|
||||||
escort_targets = [] # type: typing.List[PlaneGroup]
|
escort_targets = [] # type: typing.List[PlaneGroup]
|
||||||
|
|
||||||
@ -37,8 +38,7 @@ class AircraftConflictGenerator:
|
|||||||
int(self.conflict.size * SPREAD_DISTANCE_FACTOR[0]),
|
int(self.conflict.size * SPREAD_DISTANCE_FACTOR[0]),
|
||||||
int(self.conflict.size * SPREAD_DISTANCE_FACTOR[1]),
|
int(self.conflict.size * SPREAD_DISTANCE_FACTOR[1]),
|
||||||
)
|
)
|
||||||
|
return point.random_point_within(distance, self.conflict.size * SPREAD_DISTANCE_FACTOR[0])
|
||||||
return point.random_point_within(distance, self.conflict.size * SPREAD_DISTANCE_SIZE_FACTOR)
|
|
||||||
|
|
||||||
def _generate_group(
|
def _generate_group(
|
||||||
self,
|
self,
|
||||||
@ -48,7 +48,7 @@ class AircraftConflictGenerator:
|
|||||||
count: int,
|
count: int,
|
||||||
at: Point = None,
|
at: Point = None,
|
||||||
airport: Airport = None) -> PlaneGroup:
|
airport: Airport = None) -> PlaneGroup:
|
||||||
starttype = airport == None and StartType.Warm or StartType.Runway
|
starttype = airport == None and StartType.Warm or StartType.Cold
|
||||||
return self.m.flight_group(
|
return self.m.flight_group(
|
||||||
country=side,
|
country=side,
|
||||||
name=name,
|
name=name,
|
||||||
@ -86,9 +86,14 @@ class AircraftConflictGenerator:
|
|||||||
airport=airport)
|
airport=airport)
|
||||||
|
|
||||||
group.task = Escort.name
|
group.task = Escort.name
|
||||||
for group in self.escort_targets:
|
group.load_task_default_loadout(dcs.task.Escort.name)
|
||||||
group.tasks.append(EscortTaskAction(group.id, engagement_max_dist=ESCORT_MAX_DIST))
|
|
||||||
|
|
||||||
|
heading = group.position.heading_between_point(self.conflict.point)
|
||||||
|
position = group.position # type: Point
|
||||||
|
wayp = group.add_waypoint(position.point_from_heading(heading, 3000), CAS_ALTITUDE)
|
||||||
|
|
||||||
|
for group in self.escort_targets:
|
||||||
|
wayp.tasks.append(EscortTaskAction(group.id, engagement_max_dist=ESCORT_MAX_DIST))
|
||||||
|
|
||||||
def generate_interceptors(self, defenders: typing.Dict[PlaneType, int], airport: Airport = None):
|
def generate_interceptors(self, defenders: typing.Dict[PlaneType, int], airport: Airport = None):
|
||||||
for type, count in defenders.items():
|
for type, count in defenders.items():
|
||||||
@ -100,5 +105,8 @@ class AircraftConflictGenerator:
|
|||||||
at=airport == None and self._group_point(self.conflict.air_defenders_location) or None,
|
at=airport == None and self._group_point(self.conflict.air_defenders_location) or None,
|
||||||
airport=airport)
|
airport=airport)
|
||||||
|
|
||||||
group.add_waypoint(self.conflict.point, CAS_ALTITUDE)
|
group.task = FighterSweep.name
|
||||||
group.task = FighterSweep()
|
group.load_task_default_loadout(dcs.task.FighterSweep())
|
||||||
|
wayp = group.add_waypoint(self.conflict.point, CAS_ALTITUDE)
|
||||||
|
wayp.tasks.append(dcs.task.EngageTargets(max_distance=self.conflict.size * INTERCEPT_MAX_DISTANCE_FACTOR))
|
||||||
|
wayp.tasks.append(dcs.task.OrbitAction())
|
||||||
|
|||||||
@ -18,8 +18,8 @@ from dcs.point import *
|
|||||||
from dcs.task import *
|
from dcs.task import *
|
||||||
from dcs.country import *
|
from dcs.country import *
|
||||||
|
|
||||||
SPREAD_DISTANCE_FACTOR = 0.01, 0.1
|
SPREAD_DISTANCE_FACTOR = 0.1, 0.3
|
||||||
SPREAD_DISTANCE_SIZE_FACTOR = 0.5
|
SPREAD_DISTANCE_SIZE_FACTOR = 0.1
|
||||||
|
|
||||||
class ArmorConflictGenerator:
|
class ArmorConflictGenerator:
|
||||||
def __init__(self, mission: Mission, conflict: Conflict):
|
def __init__(self, mission: Mission, conflict: Conflict):
|
||||||
@ -42,7 +42,7 @@ class ArmorConflictGenerator:
|
|||||||
unit,
|
unit,
|
||||||
position=self._group_point(at),
|
position=self._group_point(at),
|
||||||
group_size=1,
|
group_size=1,
|
||||||
move_formation=PointAction.OnRoad)
|
move_formation=PointAction.OffRoad)
|
||||||
wayp = group.add_waypoint(self.conflict.point)
|
wayp = group.add_waypoint(self.conflict.point)
|
||||||
wayp.tasks = []
|
wayp.tasks = []
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import typing
|
|||||||
import pdb
|
import pdb
|
||||||
import dcs
|
import dcs
|
||||||
|
|
||||||
|
from dcs import Mission
|
||||||
|
|
||||||
from dcs.mission import *
|
from dcs.mission import *
|
||||||
from dcs.vehicles import *
|
from dcs.vehicles import *
|
||||||
from dcs.unitgroup import *
|
from dcs.unitgroup import *
|
||||||
@ -14,18 +16,22 @@ from dcs.country import *
|
|||||||
def _opposite_heading(h):
|
def _opposite_heading(h):
|
||||||
return h+180
|
return h+180
|
||||||
|
|
||||||
GROUND_DISTANCE_FACTOR = 1
|
GROUND_DISTANCE_FACTOR = 2
|
||||||
AIR_DISTANCE_FACTOR = 4
|
AIR_DISTANCE_FACTOR = 5
|
||||||
|
|
||||||
class Conflict:
|
class Conflict:
|
||||||
def __init__(self, heading: int, attacker: Country, defender: Country, point: Point, size: int):
|
trigger_zone = None # type: TriggerZone
|
||||||
|
activation_trigger = None # type: Trigger
|
||||||
|
|
||||||
|
def __init__(self, attacker: Country, attack_heading: int, defender: Country, defense_heading: int, point: Point, size: int):
|
||||||
self.attackers_side = attacker
|
self.attackers_side = attacker
|
||||||
self.defenders_side = defender
|
self.defenders_side = defender
|
||||||
self.point = point
|
self.point = point
|
||||||
self.size = size
|
self.size = size
|
||||||
|
|
||||||
self.ground_attackers_location = self.point.point_from_heading(heading, self.size * GROUND_DISTANCE_FACTOR)
|
self.ground_attackers_location = self.point.point_from_heading(attack_heading, self.size * GROUND_DISTANCE_FACTOR)
|
||||||
self.ground_defenders_location = self.point.point_from_heading(_opposite_heading(heading), self.size * GROUND_DISTANCE_FACTOR)
|
self.ground_defenders_location = self.point.point_from_heading(defense_heading, self.size * GROUND_DISTANCE_FACTOR)
|
||||||
|
|
||||||
|
self.air_attackers_location = self.point.point_from_heading(attack_heading, self.size * AIR_DISTANCE_FACTOR)
|
||||||
|
self.air_defenders_location = self.point.point_from_heading(defense_heading, self.size * AIR_DISTANCE_FACTOR)
|
||||||
|
|
||||||
self.air_attackers_location = self.point.point_from_heading(heading, self.size * AIR_DISTANCE_FACTOR)
|
|
||||||
self.air_defenders_location = self.point.point_from_heading(_opposite_heading(heading), self.size * AIR_DISTANCE_FACTOR)
|
|
||||||
|
|||||||
@ -16,6 +16,10 @@ class NameGenerator:
|
|||||||
def next_intercept_group_name(self):
|
def next_intercept_group_name(self):
|
||||||
self.number += 1
|
self.number += 1
|
||||||
return "Intercept Unit {}".format(self.number)
|
return "Intercept Unit {}".format(self.number)
|
||||||
|
|
||||||
|
def next_ground_group_name(self):
|
||||||
|
self.number += 1
|
||||||
|
return "AA Unit {}".format(self.number)
|
||||||
|
|
||||||
|
|
||||||
namegen = NameGenerator()
|
namegen = NameGenerator()
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
import dcs
|
|
||||||
|
|
||||||
class ControlPoint:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
11
theater/base.py
Normal file
11
theater/base.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import typing
|
||||||
|
import dcs
|
||||||
|
|
||||||
|
from .controlpoint import *
|
||||||
|
|
||||||
|
from dcs.planes import *
|
||||||
|
from dcs.vehicles import *
|
||||||
|
|
||||||
|
class Base:
|
||||||
|
aircraft = [] # type: typing.Dict[PlaneType, int]
|
||||||
|
armor = [] # type: typing.Dict[Armor, int]
|
||||||
14
theater/caucasus.py
Normal file
14
theater/caucasus.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from dcs.terrain import caucasus
|
||||||
|
|
||||||
|
from .conflicttheater import *
|
||||||
|
from .base import *
|
||||||
|
|
||||||
|
class CaucasusTheater(ConflictTheater):
|
||||||
|
sukhumi = ControlPoint(caucasus.Sukhumi().position, 1000, 5, True, Base())
|
||||||
|
krymsk = ControlPoint(caucasus.Krymsk().position, 1500, 10, False, None)
|
||||||
|
kransnodar = ControlPoint(caucasus.KrasnodarCenter().position, 3000, 30, False, Base())
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.add_controlpoint(self.sukhumi, [self.krymsk])
|
||||||
|
self.add_controlpoint(self.krymsk, [self.sukhumi, self.kransnodar])
|
||||||
|
self.add_controlpoint(self.kransnodar, [self.krymsk])
|
||||||
16
theater/conflicttheater.py
Normal file
16
theater/conflicttheater.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import typing
|
||||||
|
import dcs
|
||||||
|
|
||||||
|
from .controlpoint import *
|
||||||
|
|
||||||
|
class ConflictTheater:
|
||||||
|
controlpoints = [] # type: typing.Collection[ControlPoint]
|
||||||
|
|
||||||
|
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint]):
|
||||||
|
for connected_point in connected_to:
|
||||||
|
point.connect(to=connected_point)
|
||||||
|
|
||||||
|
self.controlpoints.append(point)
|
||||||
|
|
||||||
|
def player_bases(self) -> typing.Collection[ControlPoint]:
|
||||||
|
return [point for point in self.controlpoints if point.captured and point.base]
|
||||||
30
theater/controlpoint.py
Normal file
30
theater/controlpoint.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import typing
|
||||||
|
import dcs
|
||||||
|
|
||||||
|
from dcs.mapping import *
|
||||||
|
from dcs.country import *
|
||||||
|
|
||||||
|
from gen.conflictgen import Conflict
|
||||||
|
from .base import *
|
||||||
|
|
||||||
|
class ControlPoint:
|
||||||
|
connected_points = [] # type: typing.Collection[ControlPoint]
|
||||||
|
point = None # type: Point
|
||||||
|
captured = False
|
||||||
|
base = None # type: Base
|
||||||
|
|
||||||
|
def __init__(self, point: Point, size: int, importance: int, captured: bool, base: Base):
|
||||||
|
self.point = point
|
||||||
|
self.size = size
|
||||||
|
self.importance = importance
|
||||||
|
self.captured = captured
|
||||||
|
self.base = base
|
||||||
|
|
||||||
|
def connect(self, to):
|
||||||
|
self.connected_points.append(to)
|
||||||
|
|
||||||
|
def conflict_attack(self, x, attacker: Country, defender: Country) -> Conflict:
|
||||||
|
#heading = heading_between_points(self.point.x, self.point.y, x.point.x, x.point.y)
|
||||||
|
return Conflict(attacker, 0, defender, 90, self.point, self.size)
|
||||||
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user