randomized strike objects with templates; forbid ground objects and vehicles placement on mountains and in forests; updated push trigger so it include player group; adjacent CP missions could be initiated from carriers

This commit is contained in:
Vasyl Horbachenko 2018-10-11 03:45:20 +03:00
parent 8431c7745d
commit e28a24c875
24 changed files with 228 additions and 62 deletions

View File

@ -70,7 +70,8 @@ try:
for i in range(0, int(len(conflicttheater.controlpoints) / 2)): for i in range(0, int(len(conflicttheater.controlpoints) / 2)):
conflicttheater.controlpoints[i].captured = True conflicttheater.controlpoints[i].captured = True
start_generator.generate_initial(conflicttheater, enemy_name, sams, multiplier) start_generator.generate_inital_units(conflicttheater, enemy_name, sams, multiplier)
start_generator.generate_groundobjects(conflicttheater)
game = Game(player_name=player_name, game = Game(player_name=player_name,
enemy_name=enemy_name, enemy_name=enemy_name,
theater=conflicttheater) theater=conflicttheater)

View File

@ -112,14 +112,18 @@ class Game:
enemy_generated_types = [] enemy_generated_types = []
for player_cp, enemy_cp in self.theater.conflicts(True): for player_cp, enemy_cp in self.theater.conflicts(True):
if player_cp.is_global or enemy_cp.is_global: if enemy_cp.is_global:
continue continue
for event_class, (player_probability, enemy_probability) in EVENT_PROBABILITIES.items(): for event_class, (player_probability, enemy_probability) in EVENT_PROBABILITIES.items():
if event_class == FrontlineAttackEvent or event_class == InfantryTransportEvent or event_class == FrontlinePatrolEvent: if event_class in [FrontlineAttackEvent, FrontlinePatrolEvent, InfantryTransportEvent]:
if not Conflict.has_frontline_between(player_cp, enemy_cp): if not Conflict.has_frontline_between(player_cp, enemy_cp):
continue continue
if player_cp.is_global:
if event_class not in [InterceptEvent, StrikeEvent, NavalInterceptEvent]:
continue
if player_probability == 100 or self._roll(player_probability, player_cp.base.strength): if player_probability == 100 or self._roll(player_probability, player_cp.base.strength):
if event_class == NavalInterceptEvent and enemy_cp.radials == LAND: if event_class == NavalInterceptEvent and enemy_cp.radials == LAND:
pass pass

View File

@ -47,7 +47,9 @@ class FrontlineAttackOperation(Operation):
self.briefinggen.append_frequency("FARP", "127.5 MHz AM") self.briefinggen.append_frequency("FARP", "127.5 MHz AM")
for farp, dict in zip(self.groundobjectgen.generate_farps(sum([x[0] for x in heli_flights.values()])), for farp, dict in zip(self.groundobjectgen.generate_farps(sum([x[0] for x in heli_flights.values()])),
db.assignedunits_split_to_count(heli_flights, self.groundobjectgen.FARP_CAPACITY)): db.assignedunits_split_to_count(heli_flights, self.groundobjectgen.FARP_CAPACITY)):
self.airgen.generate_cas_strikegroup(*assigned_units_split(dict), at=farp, escort=False) self.airgen.generate_cas_strikegroup(*assigned_units_split(dict),
at=farp,
escort=len(planes_flights) == 0)
self.briefinggen.title = "Frontline CAS" self.briefinggen.title = "Frontline CAS"
self.briefinggen.description = "Provide CAS for the ground forces attacking enemy lines. Operation will be considered successful if total number of enemy units will be lower than your own by a factor of 1.5 (i.e. with 12 units from both sides, enemy forces need to be reduced to at least 8), meaning that you (and, probably, your wingmans) should concentrate on destroying the enemy units. Target base strength will be lowered as a result. Be advised that your flight will not attack anything until you explicitly tell them so by comms menu." self.briefinggen.description = "Provide CAS for the ground forces attacking enemy lines. Operation will be considered successful if total number of enemy units will be lower than your own by a factor of 1.5 (i.e. with 12 units from both sides, enemy forces need to be reduced to at least 8), meaning that you (and, probably, your wingmans) should concentrate on destroying the enemy units. Target base strength will be lowered as a result. Be advised that your flight will not attack anything until you explicitly tell them so by comms menu."

View File

@ -52,12 +52,22 @@ class StrikeOperation(Operation):
targets.sort(key=lambda x: self.from_cp.position.distance_to_point(x[1])) targets.sort(key=lambda x: self.from_cp.position.distance_to_point(x[1]))
self.airgen.generate_ground_attack_strikegroup(*assigned_units_split(self.strikegroup), planes_flights = {k: v for k, v in self.strikegroup.items() if k in plane_map.values()}
self.airgen.generate_ground_attack_strikegroup(*assigned_units_split(planes_flights),
targets=targets, targets=targets,
at=self.attackers_starting_position) at=self.attackers_starting_position)
self.airgen.generate_attackers_escort(*assigned_units_split(self.escort), at=self.attackers_starting_position) heli_flights = {k: v for k, v in self.strikegroup.items() if k in helicopters.helicopter_map.values()}
if heli_flights:
self.briefinggen.append_frequency("FARP", "127.5 MHz AM")
for farp, dict in zip(self.groundobjectgen.generate_farps(sum([x[0] for x in heli_flights.values()])),
db.assignedunits_split_to_count(heli_flights, self.groundobjectgen.FARP_CAPACITY)):
self.airgen.generate_ground_attack_strikegroup(*assigned_units_split(dict),
targets=targets,
at=farp,
escort=len(planes_flights) == 0)
self.airgen.generate_attackers_escort(*assigned_units_split(self.escort), at=self.attackers_starting_position)
self.airgen.generate_barcap(*assigned_units_split(self.interceptors), at=self.defenders_starting_position) self.airgen.generate_barcap(*assigned_units_split(self.interceptors), at=self.defenders_starting_position)
self.briefinggen.title = "Strike" self.briefinggen.title = "Strike"

View File

@ -21,6 +21,10 @@ class AirSupportConflictGenerator:
self.conflict = conflict self.conflict = conflict
self.game = game self.game = game
@classmethod
def support_tasks(cls) -> typing.Collection[typing.Type[MainTask]]:
return [Refueling, AWACS]
def generate(self, is_awacs_enabled): def generate(self, is_awacs_enabled):
player_cp = self.conflict.from_cp if self.conflict.from_cp.captured else self.conflict.to_cp player_cp = self.conflict.from_cp if self.conflict.from_cp.captured else self.conflict.to_cp
tanker_unit = db.find_unittype(Refueling, self.conflict.attackers_side.name)[0] tanker_unit = db.find_unittype(Refueling, self.conflict.attackers_side.name)[0]

View File

@ -130,19 +130,22 @@ class Conflict:
return self.to_cp.size * GROUND_DISTANCE_FACTOR return self.to_cp.size * GROUND_DISTANCE_FACTOR
def find_insertion_point(self, other_point: Point) -> Point: def find_insertion_point(self, other_point: Point) -> Point:
dx = self.position.x - self.tail.x if self.is_vector:
dy = self.position.y - self.tail.y dx = self.position.x - self.tail.x
dr2 = float(dx ** 2 + dy ** 2) dy = self.position.y - self.tail.y
dr2 = float(dx ** 2 + dy ** 2)
lerp = ((other_point.x - self.tail.x) * dx + (other_point.y - self.tail.y) * dy) / dr2 lerp = ((other_point.x - self.tail.x) * dx + (other_point.y - self.tail.y) * dy) / dr2
if lerp < 0: if lerp < 0:
lerp = 0 lerp = 0
elif lerp > 1: elif lerp > 1:
lerp = 1 lerp = 1
x = lerp * dx + self.tail.x x = lerp * dx + self.tail.x
y = lerp * dy + self.tail.y y = lerp * dy + self.tail.y
return Point(x, y) return Point(x, y)
else:
return self.position
def find_ground_position(self, at: Point, heading: int, max_distance: int = 40000) -> typing.Optional[Point]: def find_ground_position(self, at: Point, heading: int, max_distance: int = 40000) -> typing.Optional[Point]:
return Conflict._find_ground_position(at, max_distance, heading, self.theater) return Conflict._find_ground_position(at, max_distance, heading, self.theater)
@ -153,7 +156,10 @@ class Conflict:
@classmethod @classmethod
def frontline_position(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> typing.Tuple[Point, int]: def frontline_position(cls, from_cp: ControlPoint, to_cp: ControlPoint) -> typing.Tuple[Point, int]:
distance = max(from_cp.position.distance_to_point(to_cp.position) * FRONTLINE_DISTANCE_STRENGTH_FACTOR * to_cp.base.strength, FRONTLINE_MIN_CP_DISTANCE) cp_distance = from_cp.position.distance_to_point(to_cp.position)
cp_distance -= cp_distance * to_cp.frontline_offset + cp_distance * from_cp.frontline_offset
distance = max(cp_distance * FRONTLINE_DISTANCE_STRENGTH_FACTOR * to_cp.base.strength, FRONTLINE_MIN_CP_DISTANCE)
heading = to_cp.position.heading_between_point(from_cp.position) heading = to_cp.position.heading_between_point(from_cp.position)
return to_cp.position.point_from_heading(heading, distance), heading return to_cp.position.point_from_heading(heading, distance), heading
@ -172,7 +178,6 @@ class Conflict:
if pos: if pos:
left_position = pos left_position = pos
center_position = pos center_position = pos
print("{} - {} {}".format(from_cp, to_cp, center_position))
if left_position is None: if left_position is None:
left_position = cls._extend_ground_position(center_position, int(FRONTLINE_LENGTH/2), _heading_sum(heading, -90), theater) left_position = cls._extend_ground_position(center_position, int(FRONTLINE_LENGTH/2), _heading_sum(heading, -90), theater)

View File

@ -19,11 +19,15 @@ class GroundObjectsGenerator:
self.game = game self.game = game
def generate_farps(self, number_of_units=1) -> typing.Collection[StaticGroup]: def generate_farps(self, number_of_units=1) -> typing.Collection[StaticGroup]:
assert self.conflict.is_vector, "FARP could be generated only on frontline conflicts!" if self.conflict.is_vector:
center = self.conflict.center
for i, _ in enumerate(range(0, number_of_units, self.FARP_CAPACITY)):
heading = self.conflict.heading - 90 heading = self.conflict.heading - 90
position = self.conflict.find_ground_position(self.conflict.center.point_from_heading(heading, FARP_FRONTLINE_DISTANCE), heading) else:
center, heading = self.conflict.frontline_position(self.conflict.from_cp, self.conflict.to_cp)
heading -= 90
position = self.conflict.find_ground_position(center.point_from_heading(heading, FARP_FRONTLINE_DISTANCE), heading)
for i, _ in enumerate(range(0, number_of_units, self.FARP_CAPACITY)):
position = position.point_from_heading(0, i * 275) position = position.point_from_heading(0, i * 275)
yield self.m.farp( yield self.m.farp(
@ -64,6 +68,10 @@ class GroundObjectsGenerator:
else: else:
static_type = fortification_map[ground_object.dcs_identifier] static_type = fortification_map[ground_object.dcs_identifier]
if not static_type:
print("Didn't find {} in static _map(s)!".format(ground_object.dcs_identifier))
continue
group = self.m.static_group( group = self.m.static_group(
country=side, country=side,
name=ground_object.string_identifier, name=ground_object.string_identifier,

View File

@ -12,9 +12,11 @@ from dcs.action import *
from game import db from game import db
from theater import * from theater import *
from gen.airsupportgen import AirSupportConflictGenerator
from gen import * from gen import *
PUSH_TRIGGER_SIZE = 3000 PUSH_TRIGGER_SIZE = 3000
PUSH_TRIGGER_ACTIVATION_AGL = 100
REGROUP_ZONE_DISTANCE = 12000 REGROUP_ZONE_DISTANCE = 12000
REGROUP_ALT = 5000 REGROUP_ALT = 5000
@ -51,6 +53,11 @@ class TriggersGenerator:
vehicle_group.late_activation = True vehicle_group.late_activation = True
activate_by_trigger.append(vehicle_group) activate_by_trigger.append(vehicle_group)
for plane_group in country.plane_group:
if plane_group.task in [x.name for x in AirSupportConflictGenerator.support_tasks()]:
plane_group.late_activation = True
activate_by_trigger.append(plane_group)
conflict_distance = player_cp.position.distance_to_point(self.conflict.position) conflict_distance = player_cp.position.distance_to_point(self.conflict.position)
minimum_radius = max(conflict_distance - TRIGGER_MIN_DISTANCE_FROM_START, TRIGGER_RADIUS_MINIMUM) minimum_radius = max(conflict_distance - TRIGGER_MIN_DISTANCE_FROM_START, TRIGGER_RADIUS_MINIMUM)
if minimum_radius < 0: if minimum_radius < 0:
@ -79,9 +86,6 @@ class TriggersGenerator:
if player_cp.position.distance_to_point(group.position) > PUSH_TRIGGER_SIZE * 3: if player_cp.position.distance_to_point(group.position) > PUSH_TRIGGER_SIZE * 3:
continue continue
if group.units[0].is_human():
continue
regroup_heading = self.conflict.to_cp.position.heading_between_point(player_cp.position) regroup_heading = self.conflict.to_cp.position.heading_between_point(player_cp.position)
pos1 = group.position.point_from_heading(regroup_heading, REGROUP_ZONE_DISTANCE) pos1 = group.position.point_from_heading(regroup_heading, REGROUP_ZONE_DISTANCE)
@ -109,7 +113,9 @@ class TriggersGenerator:
push_trigger = TriggerOnce(Event.NoEvent, "Push trigger") push_trigger = TriggerOnce(Event.NoEvent, "Push trigger")
for group in push_by_trigger: for group in push_by_trigger:
push_trigger.add_condition(AllOfGroupOutsideZone(group.id, push_trigger_zone.id)) for unit in group.units:
push_trigger.add_condition(UnitAltitudeHigherAGL(unit.id, PUSH_TRIGGER_ACTIVATION_AGL))
push_trigger.add_action(AITaskPush(group.id, 1)) push_trigger.add_action(AITaskPush(group.id, 1))
message_string = self.mission.string("Task force is in the air, proceed with the objective (activate waypoint 3).") message_string = self.mission.string("Task force is in the air, proceed with the objective (activate waypoint 3).")

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,49 @@
import pickle
import typing
from dcs.mission import Mission
from dcs.mapping import Point
from dcs.unit import *
from dcs.statics import warehouse_map, fortification_map
def load_templates():
temp_mis = Mission()
temp_mis.load_file("resources/tools/groundobject_templates.miz")
groups = {} # type: typing.Dict[str, typing.Dict[int, typing.Collection[Static]]]
for static_group in temp_mis.country("USA").static_group:
for static in static_group.units:
static_name = str(static.name).split()[0]
tpl_name, tpl_idx = static_name[:-1], int(static_name[-1])
groups[tpl_name] = groups.get(tpl_name, {})
groups[tpl_name][tpl_idx] = groups[tpl_name].get(tpl_idx, [])
groups[tpl_name][tpl_idx].append(static)
tpls = {name: {idx: [] for idx in groups[name].keys()} for name in groups.keys()}
for category_name, category_groups in groups.items():
for idx, static_groups in category_groups.items():
dist = -1
a, b = None, None
for aa in static_groups:
for bb in static_groups:
if aa.position.distance_to_point(bb.position) > dist:
dist = aa.position.distance_to_point(bb.position)
a = aa
b = bb
center = a.position.point_from_heading(a.position.heading_between_point(b.position), dist / 2)
for static in static_groups:
tpls[category_name][idx].append({
"type": static.type,
"offset": Point(center.x - static.position.x, center.y - static.position.y),
"heading": static.heading,
})
return tpls
with open("resources/groundobject_templates.p", "wb") as f:
pickle.dump(load_templates(), f)

View File

@ -5,6 +5,7 @@ from dcs.mission import Mission
from dcs.mapping import Point from dcs.mapping import Point
from dcs.terrain import * from dcs.terrain import *
from dcs.unitgroup import VehicleGroup, StaticGroup from dcs.unitgroup import VehicleGroup, StaticGroup
from dcs import vehicles
from dcs.unit import * from dcs.unit import *
from dcs.statics import warehouse_map, fortification_map from dcs.statics import warehouse_map, fortification_map
@ -51,7 +52,7 @@ if __name__ == "__main__":
theater_object.position = unit.position theater_object.position = unit.position
theater_object.heading = unit.heading theater_object.heading = unit.heading
if isinstance(unit, Vehicle): if isinstance(unit, Vehicle) and unit.type in vehicles.AirDefence.__dict__.values():
theater_object.dcs_identifier = "AA" theater_object.dcs_identifier = "AA"
else: else:
theater_object.dcs_identifier = unit.type theater_object.dcs_identifier = unit.type

View File

@ -1,14 +1,26 @@
import pickle import pickle
from dcs.mission import Mission from dcs.mission import Mission
from dcs.planes import A_10C
for terrain in ["cau", "gulf"]: for terrain in ["cau", "gulf"]:
m = Mission() m = Mission()
m.load_file("./{}_terrain.miz".format(terrain)) m.load_file("./{}_terrain.miz".format(terrain))
landmap = [] inclusion_zones = []
exclusion_zones = []
for plane_group in m.country("USA").plane_group: for plane_group in m.country("USA").plane_group:
landmap.append([(x.position.x, x.position.y) for x in plane_group.points]) zone = [(x.position.x, x.position.y) for x in plane_group.points]
if terrain == "cau" and inclusion_zones:
# legacy
exclusion_zones.append(zone)
else:
if plane_group.units[0].type == "F-15C":
exclusion_zones.append(zone)
else:
inclusion_zones.append(zone)
with open("../{}landmap.p".format(terrain), "wb") as f: with open("../{}landmap.p".format(terrain), "wb") as f:
pickle.dump(landmap, f) print(len(inclusion_zones), len(exclusion_zones))
pickle.dump((inclusion_zones, exclusion_zones), f)

Binary file not shown.

Binary file not shown.

View File

@ -47,6 +47,9 @@ class CaucasusTheater(ConflictTheater):
def __init__(self, load_ground_objects=True): def __init__(self, load_ground_objects=True):
super(CaucasusTheater, self).__init__() super(CaucasusTheater, self).__init__()
self.soganlug.frontline_offset = 0.5
self.soganlug.base.strength = 1
self.add_controlpoint(self.soganlug, connected_to=[self.kutaisi, self.beslan]) self.add_controlpoint(self.soganlug, connected_to=[self.kutaisi, self.beslan])
self.add_controlpoint(self.beslan, connected_to=[self.soganlug, self.mozdok, self.nalchik]) self.add_controlpoint(self.beslan, connected_to=[self.soganlug, self.mozdok, self.nalchik])
self.add_controlpoint(self.nalchik, connected_to=[self.beslan, self.mozdok, self.mineralnye]) self.add_controlpoint(self.nalchik, connected_to=[self.beslan, self.mozdok, self.mineralnye])
@ -73,10 +76,6 @@ class CaucasusTheater(ConflictTheater):
self.carrier_1.captured = True self.carrier_1.captured = True
self.soganlug.captured = True self.soganlug.captured = True
if load_ground_objects:
with open("resources/cau_groundobjects.p", "rb") as f:
self.set_groundobject(pickle.load(f))
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []): def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []):
point.name = " ".join(re.split(r"[ -]", point.name)[:1]) point.name = " ".join(re.split(r"[ -]", point.name)[:1])

View File

@ -18,6 +18,8 @@ IMPORTANCE_LOW = 1
IMPORTANCE_MEDIUM = 1.2 IMPORTANCE_MEDIUM = 1.2
IMPORTANCE_HIGH = 1.4 IMPORTANCE_HIGH = 1.4
GLOBAL_CP_CONFLICT_DISTANCE_MIN = 340000
""" """
ALL_RADIALS = [0, 45, 90, 135, 180, 225, 270, 315, ] ALL_RADIALS = [0, 45, 90, 135, 180, 225, 270, 315, ]
COAST_NS_E = [45, 90, 135, ] COAST_NS_E = [45, 90, 135, ]
@ -58,31 +60,28 @@ class ConflictTheater:
def __init__(self): def __init__(self):
self.controlpoints = [] self.controlpoints = []
def set_groundobject(self, dictionary: typing.Dict[int, typing.Collection[TheaterGroundObject]]):
for id, value in dictionary.items():
for cp in self.controlpoints:
if cp.id == id:
cp.ground_objects = value
break
def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []): def add_controlpoint(self, point: ControlPoint, connected_to: typing.Collection[ControlPoint] = []):
for connected_point in connected_to: for connected_point in connected_to:
point.connect(to=connected_point) point.connect(to=connected_point)
self.controlpoints.append(point) self.controlpoints.append(point)
def is_in_sea(self, point: Point) -> bool:
if not self.landmap:
return False
return poly_contains(point.x, point.y, self.landmap[0][0])
def is_on_land(self, point: Point) -> bool: def is_on_land(self, point: Point) -> bool:
if not self.landmap: if not self.landmap:
return True return True
# check first poly (main land poly) for inclusion_zone in self.landmap[0]:
if not poly_contains(point.x, point.y, self.landmap[0]): if not poly_contains(point.x, point.y, inclusion_zone):
return False return False
# check others polys (exclusion zones from main) for exclusion_zone in self.landmap[1]:
for poly in self.landmap[1:]: if poly_contains(point.x, point.y, exclusion_zone):
if poly_contains(point.x, point.y, poly):
# point is in one of the exclusion zones, meaning that it's in the lake or something
return False return False
return True return True
@ -95,5 +94,9 @@ class ConflictTheater:
for connected_point in [x for x in cp.connected_points if x.captured != from_player]: for connected_point in [x for x in cp.connected_points if x.captured != from_player]:
yield (cp, connected_point) yield (cp, connected_point)
for global_cp in [x for x in self.controlpoints if x.is_global and x.captured == from_player]:
if global_cp.position.distance_to_point(connected_point.position) < GLOBAL_CP_CONFLICT_DISTANCE_MIN:
yield (global_cp, connected_point)
def enemy_points(self) -> typing.Collection[ControlPoint]: def enemy_points(self) -> typing.Collection[ControlPoint]:
return [point for point in self.controlpoints if not point.captured] return [point for point in self.controlpoints if not point.captured]

View File

@ -9,15 +9,20 @@ from .theatergroundobject import TheaterGroundObject
class ControlPoint: class ControlPoint:
connected_points = None # type: typing.List[ControlPoint]
ground_objects = None # type: typing.Collection[TheaterGroundObject]
position = None # type: Point
captured = False
has_frontline = True
id = 0 id = 0
position = None # type: Point
name = None # type: str
full_name = None # type: str
base = None # type: theater.base.Base base = None # type: theater.base.Base
at = None # type: db.StartPosition at = None # type: db.StartPosition
connected_points = None # type: typing.List[ControlPoint]
ground_objects = None # type: typing.List[TheaterGroundObject]
captured = False
has_frontline = True
frontline_offset = 0.0
def __init__(self, id: int, name: str, position: Point, at, radials: typing.Collection[int], size: int, importance: int, has_frontline=True): def __init__(self, id: int, name: str, position: Point, at, radials: typing.Collection[int], size: int, importance: int, has_frontline=True):
import theater.base import theater.base

View File

@ -1,7 +1,8 @@
import pickle import pickle
import typing import typing
Landmap = typing.Collection[typing.Collection[typing.Tuple[float, float]]] Zone = typing.Collection[typing.Tuple[float, float]]
Landmap = typing.Tuple[typing.Collection[Zone], typing.Collection[Zone]]
def load_landmap(filename: str) -> Landmap: def load_landmap(filename: str) -> Landmap:

View File

@ -1,4 +1,7 @@
import math import math
import pickle
import random
import typing
from theater.base import * from theater.base import *
from theater.conflicttheater import * from theater.conflicttheater import *
@ -15,7 +18,7 @@ COUNT_BY_TASK = {
} }
def generate_initial(theater: ConflictTheater, enemy: str, sams: bool, multiplier: float): def generate_inital_units(theater: ConflictTheater, enemy: str, sams: bool, multiplier: float):
for cp in theater.enemy_points(): for cp in theater.enemy_points():
if cp.captured: if cp.captured:
continue continue
@ -37,3 +40,49 @@ def generate_initial(theater: ConflictTheater, enemy: str, sams: bool, multiplie
for unit_type in unittypes: for unit_type in unittypes:
logging.info("{} - {} {}".format(cp.name, db.unit_type_name(unit_type), count_per_type)) logging.info("{} - {} {}".format(cp.name, db.unit_type_name(unit_type), count_per_type))
cp.base.commision_units({unit_type: count_per_type}) cp.base.commision_units({unit_type: count_per_type})
def generate_groundobjects(theater: ConflictTheater):
with open("resources/groundobject_templates.p", "rb") as f:
tpls = pickle.load(f)
def find_ground_location(near, theater, max, min) -> typing.Optional[Point]:
for _ in range(500):
p = near.random_point_within(max, min)
if theater.is_on_land(p):
return p
return None
group_id = 0
for cp in theater.enemy_points():
for _ in range(0, random.randrange(3, 6)):
point = find_ground_location(cp.position, theater, 120000, 5000)
if point is None:
print("Couldn't find point for {}".format(cp))
continue
dist = point.distance_to_point(cp.position)
for another_cp in theater.enemy_points():
if another_cp.position.distance_to_point(point) < dist:
cp = another_cp
tpl = random.choice(list(random.choice(list(tpls.values())).values()))
random_heading = random.randrange(0, 360)
group_id += 1
object_id = 0
for object in tpl:
object_id += 1
g = TheaterGroundObject()
g.group_id = group_id
g.object_id = object_id
g.cp_id = cp.id
g.dcs_identifier = object["type"]
g.heading = object["heading"] + random_heading
g.position = Point(point.x + object["offset"].x, point.y + object["offset"].y)
cp.ground_objects.append(g)

View File

@ -1,6 +1,7 @@
import typing import typing
from dcs.mapping import Point from dcs.mapping import Point
from dcs.statics import *
NAME_BY_CATEGORY = { NAME_BY_CATEGORY = {
"power": "Power plant", "power": "Power plant",
@ -9,6 +10,8 @@ NAME_BY_CATEGORY = {
"aa": "AA Defense Site", "aa": "AA Defense Site",
"warehouse": "Warehouse", "warehouse": "Warehouse",
"farp": "FARP", "farp": "FARP",
"fob": "FOB",
"factory": "Factory",
"comms": "Comms. tower", "comms": "Comms. tower",
"oil": "Oil platform" "oil": "Oil platform"
} }
@ -20,6 +23,8 @@ ABBREV_NAME = {
"aa": "AA", "aa": "AA",
"warehouse": "WARE", "warehouse": "WARE",
"farp": "FARP", "farp": "FARP",
"fob": "FOB",
"factory": "FACTORY",
"comms": "COMMST", "comms": "COMMST",
"oil": "OILP" "oil": "OILP"
} }
@ -27,12 +32,14 @@ ABBREV_NAME = {
CATEGORY_MAP = { CATEGORY_MAP = {
"aa": ["AA"], "aa": ["AA"],
"power": ["Workshop A"], "power": ["Workshop A", "Electric power box", "Garage A"],
"warehouse": ["Warehouse"], "warehouse": ["Warehouse", "Hangar A"],
"fuel": ["Tank"], "fuel": ["Tank", "Tank 2", "Fuel tank"],
"ammo": [".Ammunition depot"], "ammo": [".Ammunition depot", "Hangar B"],
"farp": ["FARP Tent"], "farp": ["FARP Tent", "FARP Ammo Dump Coating", "FARP Fuel Depot", "FARP Command Post", "FARP CP Blindage"],
"comms": ["TV tower", "Comms tower"], "fob": ["Bunker 2", "Bunker 1", "Garage small B", ".Command Center", "Barracks 2"],
"factory": ["Tech combine", "Tech hangar A"],
"comms": ["TV tower", "Comms tower M"],
"oil": ["Oil platform"], "oil": ["Oil platform"],
} }