dcs-retribution/gen/sam/group_generator.py
Dan Albert 56b51c85bb Fix targeting SAMs with strike missions.
The changes for Skynet unfortunately broke this because the names used
by the TGO and the name of the group itself were no longer in sync.
This deserves a larger cleanup where we decouple that naming
requirement (TGOs don't need a lot of the data they currently have),
but this works until we have the time to do that.

Fixes https://github.com/Khopa/dcs_liberation/issues/298
2020-11-07 13:37:52 -08:00

108 lines
3.9 KiB
Python

from __future__ import annotations
import math
import random
from typing import TYPE_CHECKING, Optional
from dcs import unitgroup
from dcs.point import PointAction
from dcs.unit import Vehicle, Ship
from dcs.unittype import VehicleType
from game.factions.faction import Faction
from theater.theatergroundobject import TheaterGroundObject
if TYPE_CHECKING:
from game.game import Game
# TODO: Generate a group description rather than a pydcs group.
# It appears that all of this work gets redone at miz generation time (see
# groundobjectsgen for an example). We can do less work and include the data we
# care about in the format we want if we just generate our own group description
# types rather than pydcs groups.
class GroupGenerator:
def __init__(self, game: Game, ground_object: TheaterGroundObject) -> None:
self.game = game
self.go = ground_object
self.position = ground_object.position
self.heading = random.randint(0, 359)
self.vg = unitgroup.VehicleGroup(self.game.next_group_id(),
self.go.group_name)
wp = self.vg.add_waypoint(self.position, PointAction.OffRoad, 0)
wp.ETA_locked = True
def generate(self):
raise NotImplementedError
def get_generated_group(self) -> unitgroup.VehicleGroup:
return self.vg
def add_unit(self, unit_type: VehicleType, name: str, pos_x: float,
pos_y: float, heading: int) -> Vehicle:
unit = Vehicle(self.game.next_unit_id(),
f"{self.go.group_name}|{name}", unit_type.id)
unit.position.x = pos_x
unit.position.y = pos_y
unit.heading = heading
self.vg.add_unit(unit)
return unit
def get_circular_position(self, num_units, launcher_distance, coverage=90):
"""
Given a position on the map, array a group of units in a circle a uniform distance from the unit
:param num_units:
number of units to play on the circle
:param launcher_distance:
distance the units should be from the center unit
:param coverage:
0-360
:return:
list of tuples representing each unit location
[(pos_x, pos_y, heading), ...]
"""
if coverage == 360:
# one of the positions is shared :'(
outer_offset = coverage / num_units
else:
outer_offset = coverage / (num_units - 1)
positions = []
if num_units % 2 == 0:
current_offset = self.heading - ((coverage / (num_units - 1)) / 2)
else:
current_offset = self.heading
current_offset -= outer_offset * (math.ceil(num_units / 2) - 1)
for x in range(1, num_units + 1):
positions.append((
self.position.x + launcher_distance * math.cos(math.radians(current_offset)),
self.position.y + launcher_distance * math.sin(math.radians(current_offset)),
current_offset,
))
current_offset += outer_offset
return positions
class ShipGroupGenerator(GroupGenerator):
"""Abstract class for other ship generator classes"""
def __init__(self, game: Game, ground_object: TheaterGroundObject, faction: Faction):
self.game = game
self.go = ground_object
self.position = ground_object.position
self.heading = random.randint(0, 359)
self.faction = faction
self.vg = unitgroup.ShipGroup(self.game.next_group_id(),
self.go.group_name)
wp = self.vg.add_waypoint(self.position, 0)
wp.ETA_locked = True
def add_unit(self, unit_type, name, pos_x, pos_y, heading) -> Ship:
unit = Ship(self.game.next_unit_id(),
f"{self.go.group_name}|{name}", unit_type)
unit.position.x = pos_x
unit.position.y = pos_y
unit.heading = heading
self.vg.add_unit(unit)
return unit