mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Add a wrapper type for ground unit info.
This commit is contained in:
@@ -110,7 +110,6 @@ class AirSupportConflictGenerator:
|
||||
):
|
||||
# TODO: Make loiter altitude a property of the unit type.
|
||||
alt, airspeed = self._get_tanker_params(tanker_unit_type.dcs_unit_type)
|
||||
variant = db.unit_type_name(tanker_unit_type)
|
||||
freq = self.radio_registry.alloc_uhf()
|
||||
tacan = self.tacan_registry.alloc_for_band(TacanBand.Y)
|
||||
tanker_heading = (
|
||||
@@ -175,7 +174,7 @@ class AirSupportConflictGenerator:
|
||||
TankerInfo(
|
||||
str(tanker_group.name),
|
||||
callsign,
|
||||
variant,
|
||||
tanker_unit_type.name,
|
||||
freq,
|
||||
tacan,
|
||||
blue=True,
|
||||
|
||||
76
gen/armor.py
76
gen/armor.py
@@ -10,7 +10,6 @@ from dcs.action import AITaskPush
|
||||
from dcs.condition import GroupLifeLess, Or, TimeAfter, UnitDamaged
|
||||
from dcs.country import Country
|
||||
from dcs.mapping import Point
|
||||
from dcs.planes import MQ_9_Reaper
|
||||
from dcs.point import PointAction
|
||||
from dcs.task import (
|
||||
EPLRS,
|
||||
@@ -26,19 +25,18 @@ from dcs.task import (
|
||||
from dcs.triggers import Event, TriggerOnce
|
||||
from dcs.unit import Vehicle
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
from dcs.unittype import VehicleType
|
||||
from game import db
|
||||
|
||||
from game.data.groundunitclass import GroundUnitClass
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
from game.theater.controlpoint import ControlPoint
|
||||
from game.unitmap import UnitMap
|
||||
from game.utils import heading_sum, opposite_heading
|
||||
from game.theater.controlpoint import ControlPoint
|
||||
|
||||
from gen.ground_forces.ai_ground_planner import (
|
||||
DISTANCE_FROM_FRONTLINE,
|
||||
CombatGroup,
|
||||
CombatGroupRole,
|
||||
)
|
||||
|
||||
from .callsigns import callsign_for_support_unit
|
||||
from .conflictgen import Conflict
|
||||
from .ground_forces.combat_stance import CombatStance
|
||||
@@ -226,19 +224,18 @@ class GroundConflictGenerator:
|
||||
else:
|
||||
cp = self.conflict.red_cp
|
||||
|
||||
if is_player:
|
||||
faction = self.game.player_name
|
||||
else:
|
||||
faction = self.game.enemy_name
|
||||
faction = self.game.faction_for(is_player)
|
||||
|
||||
# Disable infantry unit gen if disabled
|
||||
if not self.game.settings.perf_infantry:
|
||||
if self.game.settings.manpads:
|
||||
# 50% of armored units protected by manpad
|
||||
if random.choice([True, False]):
|
||||
manpads = db.find_manpad(faction)
|
||||
if len(manpads) > 0:
|
||||
u = random.choice(manpads)
|
||||
manpads = list(faction.infantry_with_class(GroundUnitClass.Manpads))
|
||||
if manpads:
|
||||
u = random.choices(
|
||||
manpads, weights=[m.spawn_weight for m in manpads]
|
||||
)[0]
|
||||
self.mission.vehicle_group(
|
||||
side,
|
||||
namegen.next_infantry_name(side, cp.id, u),
|
||||
@@ -250,30 +247,38 @@ class GroundConflictGenerator:
|
||||
)
|
||||
return
|
||||
|
||||
possible_infantry_units = db.find_infantry(
|
||||
faction, allow_manpad=self.game.settings.manpads
|
||||
possible_infantry_units = set(
|
||||
faction.infantry_with_class(GroundUnitClass.Infantry)
|
||||
)
|
||||
if len(possible_infantry_units) == 0:
|
||||
if self.game.settings.manpads:
|
||||
possible_infantry_units |= set(
|
||||
faction.infantry_with_class(GroundUnitClass.Manpads)
|
||||
)
|
||||
if not possible_infantry_units:
|
||||
return
|
||||
|
||||
u = random.choice(possible_infantry_units)
|
||||
infantry_choices = list(possible_infantry_units)
|
||||
units = random.choices(
|
||||
infantry_choices,
|
||||
weights=[u.spawn_weight for u in infantry_choices],
|
||||
k=INFANTRY_GROUP_SIZE,
|
||||
)
|
||||
self.mission.vehicle_group(
|
||||
side,
|
||||
namegen.next_infantry_name(side, cp.id, u),
|
||||
u,
|
||||
namegen.next_infantry_name(side, cp.id, units[0]),
|
||||
units[0].dcs_unit_type,
|
||||
position=infantry_position,
|
||||
group_size=1,
|
||||
heading=forward_heading,
|
||||
move_formation=PointAction.OffRoad,
|
||||
)
|
||||
|
||||
for i in range(INFANTRY_GROUP_SIZE):
|
||||
u = random.choice(possible_infantry_units)
|
||||
for unit in units[1:]:
|
||||
position = infantry_position.random_point_within(55, 5)
|
||||
self.mission.vehicle_group(
|
||||
side,
|
||||
namegen.next_infantry_name(side, cp.id, u),
|
||||
u,
|
||||
namegen.next_infantry_name(side, cp.id, unit),
|
||||
unit.dcs_unit_type,
|
||||
position=position,
|
||||
group_size=1,
|
||||
heading=forward_heading,
|
||||
@@ -313,7 +318,7 @@ class GroundConflictGenerator:
|
||||
)
|
||||
artillery_trigger.add_condition(TimeAfter(seconds=random.randint(1, 45) * 60))
|
||||
# TODO: Update to fire at group instead of point
|
||||
fire_task = FireAtPoint(target, len(gen_group.units) * 10, 100)
|
||||
fire_task = FireAtPoint(target, gen_group.size * 10, 100)
|
||||
fire_task.number = 2 if stance != CombatStance.RETREAT else 1
|
||||
dcs_group.add_trigger_action(fire_task)
|
||||
artillery_trigger.add_action(AITaskPush(dcs_group.id, len(dcs_group.tasks)))
|
||||
@@ -503,7 +508,7 @@ class GroundConflictGenerator:
|
||||
return
|
||||
|
||||
for dcs_group, group in ally_groups:
|
||||
if hasattr(group.units[0], "eplrs") and group.units[0].eplrs:
|
||||
if getattr(group.unit_type.dcs_unit_type, "eplrs", False):
|
||||
dcs_group.points[0].tasks.append(EPLRS(dcs_group.id))
|
||||
|
||||
if group.role == CombatGroupRole.ARTILLERY:
|
||||
@@ -674,7 +679,7 @@ class GroundConflictGenerator:
|
||||
Search the enemy groups for a potential target suitable to an artillery unit
|
||||
"""
|
||||
# TODO: Update to return a list of groups instead of a single point
|
||||
rng = group.units[0].threat_range
|
||||
rng = getattr(group.unit_type.dcs_unit_type, "threat_range", 0)
|
||||
if not enemy_groups:
|
||||
return None
|
||||
for _ in range(10):
|
||||
@@ -691,7 +696,7 @@ class GroundConflictGenerator:
|
||||
"""
|
||||
For artilery group, decide the distance from frontline with the range of the unit
|
||||
"""
|
||||
rg = group.units[0].threat_range - 7500
|
||||
rg = getattr(group.unit_type.dcs_unit_type, "threat_range", 0) - 7500
|
||||
if rg > DISTANCE_FROM_FRONTLINE[CombatGroupRole.ARTILLERY][1]:
|
||||
rg = random.randint(
|
||||
DISTANCE_FROM_FRONTLINE[CombatGroupRole.ARTILLERY][0],
|
||||
@@ -724,7 +729,7 @@ class GroundConflictGenerator:
|
||||
|
||||
def _generate_groups(
|
||||
self,
|
||||
groups: List[CombatGroup],
|
||||
groups: list[CombatGroup],
|
||||
frontline_vector: Tuple[Point, int, int],
|
||||
is_player: bool,
|
||||
) -> List[Tuple[VehicleGroup, CombatGroup]]:
|
||||
@@ -755,10 +760,9 @@ class GroundConflictGenerator:
|
||||
if final_position is not None:
|
||||
g = self._generate_group(
|
||||
self.mission.country(country),
|
||||
group.units[0],
|
||||
len(group.units),
|
||||
group.unit_type,
|
||||
group.size,
|
||||
final_position,
|
||||
distance_from_frontline,
|
||||
heading=opposite_heading(spawn_heading),
|
||||
)
|
||||
if is_player:
|
||||
@@ -782,10 +786,9 @@ class GroundConflictGenerator:
|
||||
def _generate_group(
|
||||
self,
|
||||
side: Country,
|
||||
unit: VehicleType,
|
||||
unit_type: GroundUnitType,
|
||||
count: int,
|
||||
at: Point,
|
||||
distance_from_frontline,
|
||||
move_formation: PointAction = PointAction.OffRoad,
|
||||
heading=0,
|
||||
) -> VehicleGroup:
|
||||
@@ -795,18 +798,17 @@ class GroundConflictGenerator:
|
||||
else:
|
||||
cp = self.conflict.red_cp
|
||||
|
||||
logging.info("armorgen: {} for {}".format(unit, side.id))
|
||||
group = self.mission.vehicle_group(
|
||||
side,
|
||||
namegen.next_unit_name(side, cp.id, unit),
|
||||
unit,
|
||||
namegen.next_unit_name(side, cp.id, unit_type),
|
||||
unit_type.dcs_unit_type,
|
||||
position=at,
|
||||
group_size=count,
|
||||
heading=heading,
|
||||
move_formation=move_formation,
|
||||
)
|
||||
|
||||
self.unit_map.add_front_line_units(group, cp)
|
||||
self.unit_map.add_front_line_units(group, cp, unit_type)
|
||||
|
||||
for c in range(count):
|
||||
vehicle: Vehicle = group.units[c]
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import itertools
|
||||
from typing import Dict, TYPE_CHECKING, Type
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from dcs import Mission
|
||||
from dcs.mapping import Point
|
||||
from dcs.point import PointAction
|
||||
from dcs.unit import Vehicle
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
from dcs.unittype import VehicleType
|
||||
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
from game.transfers import Convoy
|
||||
from game.unitmap import UnitMap
|
||||
from game.utils import kph
|
||||
@@ -50,7 +50,7 @@ class ConvoyGenerator:
|
||||
self,
|
||||
name: str,
|
||||
position: Point,
|
||||
units: Dict[Type[VehicleType], int],
|
||||
units: dict[GroundUnitType, int],
|
||||
for_player: bool,
|
||||
) -> VehicleGroup:
|
||||
country = self.mission.country(
|
||||
@@ -63,7 +63,7 @@ class ConvoyGenerator:
|
||||
group = self.mission.vehicle_group(
|
||||
country,
|
||||
name,
|
||||
main_unit_type,
|
||||
main_unit_type.dcs_unit_type,
|
||||
position=position,
|
||||
group_size=main_unit_count,
|
||||
move_formation=PointAction.OnRoad,
|
||||
@@ -76,7 +76,7 @@ class ConvoyGenerator:
|
||||
for unit_type, count in unit_types[1:]:
|
||||
for i in range(count):
|
||||
v = self.mission.vehicle(
|
||||
f"{name} Unit #{next(unit_name_counter)}", unit_type
|
||||
f"{name} Unit #{next(unit_name_counter)}", unit_type.dcs_unit_type
|
||||
)
|
||||
v.position.x = position.x
|
||||
v.position.y = next(y)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import random
|
||||
|
||||
from dcs.vehicles import Armor
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
|
||||
from game import db
|
||||
from game import db, Game
|
||||
from game.data.groundunitclass import GroundUnitClass
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
from game.theater.theatergroundobject import VehicleGroupGroundObject
|
||||
from gen.defenses.armored_group_generator import (
|
||||
ArmoredGroupGenerator,
|
||||
FixedSizeArmorGroupGenerator,
|
||||
@@ -14,8 +17,14 @@ def generate_armor_group(faction: str, game, ground_object):
|
||||
This generate a group of ground units
|
||||
:return: Generated group
|
||||
"""
|
||||
armor_types = (
|
||||
GroundUnitClass.Apc,
|
||||
GroundUnitClass.Atgm,
|
||||
GroundUnitClass.Ifv,
|
||||
GroundUnitClass.Tank,
|
||||
)
|
||||
possible_unit = [
|
||||
u for u in db.FACTIONS[faction].frontline_units if u in Armor.__dict__.values()
|
||||
u for u in db.FACTIONS[faction].frontline_units if u.unit_class in armor_types
|
||||
]
|
||||
if len(possible_unit) > 0:
|
||||
unit_type = random.choice(possible_unit)
|
||||
@@ -23,7 +32,9 @@ def generate_armor_group(faction: str, game, ground_object):
|
||||
return None
|
||||
|
||||
|
||||
def generate_armor_group_of_type(game, ground_object, unit_type):
|
||||
def generate_armor_group_of_type(
|
||||
game: Game, ground_object: VehicleGroupGroundObject, unit_type: GroundUnitType
|
||||
) -> VehicleGroup:
|
||||
"""
|
||||
This generate a group of ground units of given type
|
||||
:return: Generated group
|
||||
@@ -33,7 +44,12 @@ def generate_armor_group_of_type(game, ground_object, unit_type):
|
||||
return generator.get_generated_group()
|
||||
|
||||
|
||||
def generate_armor_group_of_type_and_size(game, ground_object, unit_type, size: int):
|
||||
def generate_armor_group_of_type_and_size(
|
||||
game: Game,
|
||||
ground_object: VehicleGroupGroundObject,
|
||||
unit_type: GroundUnitType,
|
||||
size: int,
|
||||
) -> VehicleGroup:
|
||||
"""
|
||||
This generate a group of ground units of given type and size
|
||||
:return: Generated group
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
import random
|
||||
|
||||
from game import Game
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
from game.theater.theatergroundobject import VehicleGroupGroundObject
|
||||
from gen.sam.group_generator import GroupGenerator
|
||||
|
||||
|
||||
class ArmoredGroupGenerator(GroupGenerator):
|
||||
def __init__(self, game, ground_object, unit_type):
|
||||
super(ArmoredGroupGenerator, self).__init__(game, ground_object)
|
||||
def __init__(
|
||||
self,
|
||||
game: Game,
|
||||
ground_object: VehicleGroupGroundObject,
|
||||
unit_type: GroundUnitType,
|
||||
) -> None:
|
||||
super().__init__(game, ground_object)
|
||||
self.unit_type = unit_type
|
||||
|
||||
def generate(self):
|
||||
|
||||
def generate(self) -> None:
|
||||
grid_x = random.randint(2, 3)
|
||||
grid_y = random.randint(1, 2)
|
||||
|
||||
@@ -20,7 +27,7 @@ class ArmoredGroupGenerator(GroupGenerator):
|
||||
for j in range(grid_y):
|
||||
index = index + 1
|
||||
self.add_unit(
|
||||
self.unit_type,
|
||||
self.unit_type.dcs_unit_type,
|
||||
"Armor#" + str(index),
|
||||
self.position.x + spacing * i,
|
||||
self.position.y + spacing * j,
|
||||
@@ -29,8 +36,14 @@ class ArmoredGroupGenerator(GroupGenerator):
|
||||
|
||||
|
||||
class FixedSizeArmorGroupGenerator(GroupGenerator):
|
||||
def __init__(self, game, ground_object, unit_type, size):
|
||||
super(FixedSizeArmorGroupGenerator, self).__init__(game, ground_object)
|
||||
def __init__(
|
||||
self,
|
||||
game: Game,
|
||||
ground_object: VehicleGroupGroundObject,
|
||||
unit_type: GroundUnitType,
|
||||
size: int,
|
||||
) -> None:
|
||||
super().__init__(game, ground_object)
|
||||
self.unit_type = unit_type
|
||||
self.size = size
|
||||
|
||||
@@ -41,7 +54,7 @@ class FixedSizeArmorGroupGenerator(GroupGenerator):
|
||||
for i in range(self.size):
|
||||
index = index + 1
|
||||
self.add_unit(
|
||||
self.unit_type,
|
||||
self.unit_type.dcs_unit_type,
|
||||
"Armor#" + str(index),
|
||||
self.position.x + spacing * i,
|
||||
self.position.y,
|
||||
|
||||
@@ -3,11 +3,9 @@ import random
|
||||
from enum import Enum
|
||||
from typing import Dict, List
|
||||
|
||||
from dcs.unittype import VehicleType
|
||||
|
||||
from game.theater import ControlPoint
|
||||
|
||||
from game.data.groundunitclass import GroundUnitClass
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
from game.theater import ControlPoint
|
||||
from gen.ground_forces.combat_stance import CombatStance
|
||||
|
||||
MAX_COMBAT_GROUP_PER_CP = 10
|
||||
@@ -48,17 +46,19 @@ GROUP_SIZES_BY_COMBAT_STANCE = {
|
||||
|
||||
|
||||
class CombatGroup:
|
||||
def __init__(self, role: CombatGroupRole):
|
||||
self.units: List[VehicleType] = []
|
||||
def __init__(
|
||||
self, role: CombatGroupRole, unit_type: GroundUnitType, size: int
|
||||
) -> None:
|
||||
self.unit_type = unit_type
|
||||
self.size = size
|
||||
self.role = role
|
||||
self.assigned_enemy_cp = None
|
||||
self.start_position = None
|
||||
|
||||
def __str__(self):
|
||||
s = ""
|
||||
s += "ROLE : " + str(self.role) + "\n"
|
||||
if len(self.units) > 0:
|
||||
s += "UNITS " + self.units[0].name + " * " + str(len(self.units))
|
||||
s = f"ROLE : {self.role}\n"
|
||||
if self.size:
|
||||
s += f"UNITS {self.unit_type} * {self.size}"
|
||||
return s
|
||||
|
||||
|
||||
@@ -97,28 +97,29 @@ class GroundPlanner:
|
||||
|
||||
# Create combat groups and assign them randomly to each enemy CP
|
||||
for unit_type in self.cp.base.armor:
|
||||
if unit_type in GroundUnitClass.Tank:
|
||||
unit_class = unit_type.unit_class
|
||||
if unit_class is GroundUnitClass.Tank:
|
||||
collection = self.tank_groups
|
||||
role = CombatGroupRole.TANK
|
||||
elif unit_type in GroundUnitClass.Apc:
|
||||
elif unit_class is GroundUnitClass.Apc:
|
||||
collection = self.apc_group
|
||||
role = CombatGroupRole.APC
|
||||
elif unit_type in GroundUnitClass.Artillery:
|
||||
elif unit_class is GroundUnitClass.Artillery:
|
||||
collection = self.art_group
|
||||
role = CombatGroupRole.ARTILLERY
|
||||
elif unit_type in GroundUnitClass.Ifv:
|
||||
elif unit_class is GroundUnitClass.Ifv:
|
||||
collection = self.ifv_group
|
||||
role = CombatGroupRole.IFV
|
||||
elif unit_type in GroundUnitClass.Logistics:
|
||||
elif unit_class is GroundUnitClass.Logistics:
|
||||
collection = self.logi_groups
|
||||
role = CombatGroupRole.LOGI
|
||||
elif unit_type in GroundUnitClass.Atgm:
|
||||
elif unit_class is GroundUnitClass.Atgm:
|
||||
collection = self.atgm_group
|
||||
role = CombatGroupRole.ATGM
|
||||
elif unit_type in GroundUnitClass.Shorads:
|
||||
elif unit_class is GroundUnitClass.Shorads:
|
||||
collection = self.shorad_groups
|
||||
role = CombatGroupRole.SHORAD
|
||||
elif unit_type in GroundUnitClass.Recon:
|
||||
elif unit_class is GroundUnitClass.Recon:
|
||||
collection = self.recon_groups
|
||||
role = CombatGroupRole.RECON
|
||||
else:
|
||||
@@ -137,17 +138,17 @@ class GroundPlanner:
|
||||
while available > 0:
|
||||
|
||||
if role == CombatGroupRole.SHORAD:
|
||||
n = 1
|
||||
count = 1
|
||||
else:
|
||||
n = random.choice(group_size_choice)
|
||||
if n > available:
|
||||
count = random.choice(group_size_choice)
|
||||
if count > available:
|
||||
if available >= 2:
|
||||
n = 2
|
||||
count = 2
|
||||
else:
|
||||
n = 1
|
||||
available -= n
|
||||
count = 1
|
||||
available -= count
|
||||
|
||||
group = CombatGroup(role)
|
||||
group = CombatGroup(role, unit_type, count)
|
||||
if len(self.connected_enemy_cp) > 0:
|
||||
enemy_cp = random.choice(self.connected_enemy_cp).id
|
||||
self.units_per_cp[enemy_cp].append(group)
|
||||
@@ -155,9 +156,6 @@ class GroundPlanner:
|
||||
else:
|
||||
self.reserve.append(group)
|
||||
group.assigned_enemy_cp = "__reserve__"
|
||||
|
||||
for i in range(n):
|
||||
group.units.append(unit_type)
|
||||
collection.append(group)
|
||||
|
||||
if remaining_available_frontline_units == 0:
|
||||
|
||||
@@ -3,11 +3,9 @@ import time
|
||||
from typing import List
|
||||
|
||||
from dcs.country import Country
|
||||
from dcs.unittype import UnitType
|
||||
|
||||
from game import db
|
||||
from game.dcs.aircrafttype import AircraftType
|
||||
|
||||
from game.dcs.unittype import UnitType
|
||||
from gen.flights.flight import Flight
|
||||
|
||||
ALPHA_MILITARY = [
|
||||
@@ -298,7 +296,7 @@ class NameGenerator:
|
||||
def next_unit_name(cls, country: Country, parent_base_id: int, unit_type: UnitType):
|
||||
cls.number += 1
|
||||
return "unit|{}|{}|{}|{}|".format(
|
||||
country.id, cls.number, parent_base_id, db.unit_type_name(unit_type)
|
||||
country.id, cls.number, parent_base_id, unit_type.name
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@@ -310,7 +308,7 @@ class NameGenerator:
|
||||
country.id,
|
||||
cls.infantry_number,
|
||||
parent_base_id,
|
||||
db.unit_type_name(unit_type),
|
||||
unit_type.name,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
||||
Reference in New Issue
Block a user