Merge remote-tracking branch 'khopa/develop' into develop

This commit is contained in:
Khopa 2020-12-09 22:55:24 +01:00
commit 44ed895277
5 changed files with 300 additions and 174 deletions

View File

@ -500,13 +500,13 @@ class ConflictTheater:
distances[cp.id] = dist distances[cp.id] = dist
if dist < closest_distance: if dist < closest_distance:
distances[cp.id] = dist distances[cp.id] = dist
closest_cp_id = min(distances, key=distances.get) closest_cp_id = min(distances, key=distances.get) # type: ignore
all_cp_min_distances[(control_point.id, closest_cp_id)] = distances[closest_cp_id] all_cp_min_distances[(control_point.id, closest_cp_id)] = distances[closest_cp_id]
closest_opposing_cps = [ closest_opposing_cps = [
self.find_control_point_by_id(i) self.find_control_point_by_id(i)
for i for i
in min(all_cp_min_distances, key=all_cp_min_distances.get) in min(all_cp_min_distances, key=all_cp_min_distances.get) # type: ignore
] # type: List[ControlPoint] ] # type: List[ControlPoint]
assert len(closest_opposing_cps) == 2 assert len(closest_opposing_cps) == 2
if closest_opposing_cps[0].captured: if closest_opposing_cps[0].captured:

View File

@ -20,12 +20,15 @@ from dcs.planes import (
B_17G, B_17G,
B_52H, B_52H,
Bf_109K_4, Bf_109K_4,
C_101EB,
C_101CC,
FW_190A8, FW_190A8,
FW_190D9, FW_190D9,
F_14B, F_14B,
I_16, I_16,
JF_17, JF_17,
Ju_88A4, Ju_88A4,
PlaneType,
P_47D_30, P_47D_30,
P_47D_30bl1, P_47D_30bl1,
P_47D_40, P_47D_40,
@ -791,14 +794,9 @@ class AircraftConflictGenerator:
joker_fuel=flight.flight_plan.joker_fuel joker_fuel=flight.flight_plan.joker_fuel
)) ))
# Special case so Su 33 carrier take off # Special case so Su 33 and C101 can take off
if unit_type is Su_33: if unit_type in [Su_33, C_101EB, C_101CC]:
if flight.flight_type is not CAP: self.set_reduced_fuel(flight, group, unit_type)
for unit in group.units:
unit.fuel = Su_33.fuel_max / 2.2
else:
for unit in group.units:
unit.fuel = Su_33.fuel_max * 0.8
def _generate_at_airport(self, name: str, side: Country, def _generate_at_airport(self, name: str, side: Country,
unit_type: Type[FlyingType], count: int, unit_type: Type[FlyingType], count: int,
@ -1078,6 +1076,20 @@ class AircraftConflictGenerator:
return group return group
@staticmethod
def set_reduced_fuel(flight: Flight, group: FlyingGroup, unit_type: Type[PlaneType]) -> None:
if unit_type is Su_33:
for unit in group.units:
if flight.flight_type is not CAP:
unit.fuel = Su_33.fuel_max / 2.2
else:
unit.fuel = Su_33.fuel_max * 0.8
elif unit_type in [C_101EB, C_101CC]:
for unit in group.units:
unit.fuel = unit_type.fuel_max * 0.5
else:
raise RuntimeError(f"No reduced fuel case for type {unit_type}")
@staticmethod @staticmethod
def configure_behavior( def configure_behavior(
group: FlyingGroup, group: FlyingGroup,

View File

@ -1,8 +1,9 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
import random import random
from dataclasses import dataclass from dataclasses import dataclass
from typing import List, TYPE_CHECKING, Tuple from typing import TYPE_CHECKING, List, Optional, Tuple
from dcs import Mission from dcs import Mission
from dcs.action import AITaskPush from dcs.action import AITaskPush
@ -11,34 +12,25 @@ from dcs.country import Country
from dcs.mapping import Point from dcs.mapping import Point
from dcs.planes import MQ_9_Reaper from dcs.planes import MQ_9_Reaper
from dcs.point import PointAction from dcs.point import PointAction
from dcs.task import ( from dcs.task import (EPLRS, AttackGroup, ControlledTask, FireAtPoint,
AttackGroup, GoToWaypoint, Hold, OrbitAction, SetImmortalCommand,
ControlledTask, SetInvisibleCommand)
EPLRS,
FireAtPoint,
GoToWaypoint,
Hold,
OrbitAction,
SetImmortalCommand,
SetInvisibleCommand,
)
from dcs.triggers import Event, TriggerOnce from dcs.triggers import Event, TriggerOnce
from dcs.unit import Vehicle from dcs.unit import Vehicle
from dcs.unittype import VehicleType
from dcs.unitgroup import VehicleGroup from dcs.unitgroup import VehicleGroup
from dcs.unittype import VehicleType
from game import db from game import db
from game.unitmap import UnitMap from game.unitmap import UnitMap
from .naming import namegen from game.utils import heading_sum, opposite_heading
from gen.ground_forces.ai_ground_planner import ( from game.theater.controlpoint import ControlPoint
CombatGroup, CombatGroupRole,
DISTANCE_FROM_FRONTLINE, from gen.ground_forces.ai_ground_planner import (DISTANCE_FROM_FRONTLINE,
) CombatGroup, CombatGroupRole)
from .callsigns import callsign_for_support_unit from .callsigns import callsign_for_support_unit
from .conflictgen import Conflict from .conflictgen import Conflict
from .ground_forces.combat_stance import CombatStance from .ground_forces.combat_stance import CombatStance
from game.plugins import LuaPluginManager from .naming import namegen
from game.utils import heading_sum, opposite_heading
if TYPE_CHECKING: if TYPE_CHECKING:
from game import Game from game import Game
@ -137,8 +129,22 @@ class GroundConflictGenerator:
enemy_groups = self._generate_groups(self.enemy_planned_combat_groups, frontline_vector, False) enemy_groups = self._generate_groups(self.enemy_planned_combat_groups, frontline_vector, False)
# Plan combat actions for groups # Plan combat actions for groups
self.plan_action_for_groups(self.player_stance, player_groups, enemy_groups, self.conflict.heading + 90, self.conflict.from_cp, self.conflict.to_cp) self.plan_action_for_groups(
self.plan_action_for_groups(self.enemy_stance, enemy_groups, player_groups, self.conflict.heading - 90, self.conflict.to_cp, self.conflict.from_cp) self.player_stance,
player_groups,
enemy_groups,
self.conflict.heading + 90,
self.conflict.from_cp,
self.conflict.to_cp
)
self.plan_action_for_groups(
self.enemy_stance,
enemy_groups,
player_groups,
self.conflict.heading - 90,
self.conflict.to_cp,
self.conflict.from_cp
)
# Add JTAC # Add JTAC
if self.game.player_faction.has_jtac: if self.game.player_faction.has_jtac:
@ -163,7 +169,13 @@ class GroundConflictGenerator:
callsign = callsign_for_support_unit(jtac) callsign = callsign_for_support_unit(jtac)
self.jtacs.append(JtacInfo(str(jtac.name), n, callsign, frontline, str(code))) self.jtacs.append(JtacInfo(str(jtac.name), n, callsign, frontline, str(code)))
def gen_infantry_group_for_group(self, group, is_player, side:Country, forward_heading): def gen_infantry_group_for_group(
self,
group: VehicleGroup,
is_player: bool,
side: Country,
forward_heading: int
) -> None:
infantry_position = group.points[0].position.random_point_within(250, 50) infantry_position = group.points[0].position.random_point_within(250, 50)
@ -192,8 +204,6 @@ class GroundConflictGenerator:
move_formation=PointAction.OffRoad) move_formation=PointAction.OffRoad)
return return
possible_infantry_units = db.find_infantry(faction, allow_manpad=self.game.settings.manpads) possible_infantry_units = db.find_infantry(faction, allow_manpad=self.game.settings.manpads)
if len(possible_infantry_units) == 0: if len(possible_infantry_units) == 0:
return return
@ -218,23 +228,18 @@ class GroundConflictGenerator:
heading=forward_heading, heading=forward_heading,
move_formation=PointAction.OffRoad) move_formation=PointAction.OffRoad)
def plan_action_for_groups(self, stance, ally_groups, enemy_groups, forward_heading, from_cp, to_cp): def _plan_artillery_action(
self,
if not self.game.settings.perf_moving_units: stance: CombatStance,
return gen_group: CombatGroup,
dcs_group: VehicleGroup,
for dcs_group, group in ally_groups: forward_heading: int,
target: Point
if hasattr(group.units[0], 'eplrs'): ) -> bool:
if group.units[0].eplrs: """
dcs_group.points[0].tasks.append(EPLRS(dcs_group.id)) Handles adding the DCS tasks for artillery groups for all combat stances.
Returns True if tasking was added, returns False if the stance was not a combat stance.
if group.role == CombatGroupRole.ARTILLERY: """
# Fire on any ennemy in range
if self.game.settings.perf_artillery:
target = self.get_artillery_target_in_range(dcs_group, group, enemy_groups)
if target is not None:
if stance != CombatStance.RETREAT: if stance != CombatStance.RETREAT:
hold_task = Hold() hold_task = Hold()
hold_task.number = 1 hold_task.number = 1
@ -242,13 +247,10 @@ class GroundConflictGenerator:
# Artillery strike random start # Artillery strike random start
artillery_trigger = TriggerOnce(Event.NoEvent, "ArtilleryFireTask #" + str(dcs_group.id)) artillery_trigger = TriggerOnce(Event.NoEvent, "ArtilleryFireTask #" + str(dcs_group.id))
artillery_trigger.add_condition(TimeAfter(seconds=random.randint(1, 45)* 60)) 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(group.units) * 10, 100) fire_task = FireAtPoint(target, len(gen_group.units) * 10, 100)
if stance != CombatStance.RETREAT: fire_task.number = 2 if stance != CombatStance.RETREAT else 1
fire_task.number = 2
else:
fire_task.number = 1
dcs_group.add_trigger_action(fire_task) dcs_group.add_trigger_action(fire_task)
artillery_trigger.add_action(AITaskPush(dcs_group.id, len(dcs_group.tasks))) artillery_trigger.add_action(AITaskPush(dcs_group.id, len(dcs_group.tasks)))
self.mission.triggerrules.triggers.append(artillery_trigger) self.mission.triggerrules.triggers.append(artillery_trigger)
@ -282,23 +284,51 @@ class GroundConflictGenerator:
for u in dcs_group.units: for u in dcs_group.units:
u.initial = True u.initial = True
u.heading = forward_heading + random.randint(-5,5) u.heading = forward_heading + random.randint(-5, 5)
return True
return False
elif group.role in [CombatGroupRole.TANK, CombatGroupRole.IFV]: def _plan_tank_ifv_action(
self,
stance: CombatStance,
enemy_groups: List[Tuple[VehicleGroup, CombatGroup]],
dcs_group: VehicleGroup,
forward_heading: int,
to_cp: ControlPoint,
) -> bool:
"""
Handles adding the DCS tasks for tank and IFV groups for all combat stances.
Returns True if tasking was added, returns False if the stance was not a combat stance.
"""
if stance == CombatStance.AGGRESSIVE: if stance == CombatStance.AGGRESSIVE:
# Attack nearest enemy if any # Attack nearest enemy if any
# Then move forward OR Attack enemy base if it is not too far away # Then move forward OR Attack enemy base if it is not too far away
target = self.find_nearest_enemy_group(dcs_group, enemy_groups) target = self.find_nearest_enemy_group(dcs_group, enemy_groups)
if target is not None: if target is not None:
rand_offset = Point(random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK), random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK)) rand_offset = Point(
random.randint(
-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK
),
random.randint(
-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK
)
)
dcs_group.add_waypoint(target.points[0].position + rand_offset, PointAction.OffRoad) dcs_group.add_waypoint(target.points[0].position + rand_offset, PointAction.OffRoad)
dcs_group.points[1].tasks.append(AttackGroup(target.id)) dcs_group.points[1].tasks.append(AttackGroup(target.id))
if to_cp.position.distance_to_point(dcs_group.points[0].position) <= AGGRESIVE_MOVE_DISTANCE: if (
to_cp.position.distance_to_point(dcs_group.points[0].position)
<=
AGGRESIVE_MOVE_DISTANCE
):
attack_point = to_cp.position.random_point_within(500, 0) attack_point = to_cp.position.random_point_within(500, 0)
else: else:
attack_point = self.find_offensive_point(dcs_group, forward_heading, AGGRESIVE_MOVE_DISTANCE) attack_point = self.find_offensive_point(
dcs_group.add_waypoint(attack_point, PointAction.OnRoad) dcs_group,
forward_heading,
AGGRESIVE_MOVE_DISTANCE
)
dcs_group.add_waypoint(attack_point, PointAction.OffRoad)
elif stance == CombatStance.BREAKTHROUGH: elif stance == CombatStance.BREAKTHROUGH:
# In breakthrough mode, the units will move forward # In breakthrough mode, the units will move forward
# If the enemy base is close enough, the units will attack the base # If the enemy base is close enough, the units will attack the base
@ -307,35 +337,82 @@ class GroundConflictGenerator:
attack_point = to_cp.position.random_point_within(500, 0) attack_point = to_cp.position.random_point_within(500, 0)
else: else:
attack_point = self.find_offensive_point(dcs_group, forward_heading, BREAKTHROUGH_OFFENSIVE_DISTANCE) attack_point = self.find_offensive_point(dcs_group, forward_heading, BREAKTHROUGH_OFFENSIVE_DISTANCE)
dcs_group.add_waypoint(attack_point, PointAction.OnRoad) dcs_group.add_waypoint(attack_point, PointAction.OffRoad)
elif stance == CombatStance.ELIMINATION: elif stance == CombatStance.ELIMINATION:
# In elimination mode, the units focus on destroying as much enemy groups as possible # In elimination mode, the units focus on destroying as much enemy groups as possible
targets = self.find_n_nearest_enemy_groups(dcs_group, enemy_groups, 3) targets = self.find_n_nearest_enemy_groups(dcs_group, enemy_groups, 3)
i = 1 for i, target in enumerate(targets, start=1):
for target in targets: rand_offset = Point(
rand_offset = Point(random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK), random.randint(-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK)) random.randint(
-RANDOM_OFFSET_ATTACK, RANDOM_OFFSET_ATTACK
),
random.randint(
-RANDOM_OFFSET_ATTACK,
RANDOM_OFFSET_ATTACK
)
)
dcs_group.add_waypoint(target.points[0].position+rand_offset, PointAction.OffRoad) dcs_group.add_waypoint(target.points[0].position+rand_offset, PointAction.OffRoad)
dcs_group.points[i].tasks.append(AttackGroup(target.id)) dcs_group.points[i].tasks.append(AttackGroup(target.id))
i = i + 1
if to_cp.position.distance_to_point(dcs_group.points[0].position) <= AGGRESIVE_MOVE_DISTANCE: if to_cp.position.distance_to_point(dcs_group.points[0].position) <= AGGRESIVE_MOVE_DISTANCE:
attack_point = to_cp.position.random_point_within(500, 0) attack_point = to_cp.position.random_point_within(500, 0)
dcs_group.add_waypoint(attack_point) dcs_group.add_waypoint(attack_point)
if stance != CombatStance.RETREAT: if stance != CombatStance.RETREAT:
self.add_morale_trigger(dcs_group, forward_heading) self.add_morale_trigger(dcs_group, forward_heading)
return True
return False
elif group.role in [CombatGroupRole.APC, CombatGroupRole.ATGM]: def _plan_apc_atgm_action(
self,
stance: CombatStance,
dcs_group: VehicleGroup,
forward_heading: int,
to_cp: ControlPoint,
) -> bool:
"""
Handles adding the DCS tasks for APC and ATGM groups for all combat stances.
Returns True if tasking was added, returns False if the stance was not a combat stance.
"""
if stance in [CombatStance.AGGRESSIVE, CombatStance.BREAKTHROUGH, CombatStance.ELIMINATION]: if stance in [CombatStance.AGGRESSIVE, CombatStance.BREAKTHROUGH, CombatStance.ELIMINATION]:
# APC & ATGM will never move too much forward, but will follow along any offensive # APC & ATGM will never move too much forward, but will follow along any offensive
if to_cp.position.distance_to_point(dcs_group.points[0].position) <= AGGRESIVE_MOVE_DISTANCE: if to_cp.position.distance_to_point(dcs_group.points[0].position) <= AGGRESIVE_MOVE_DISTANCE:
attack_point = to_cp.position.random_point_within(500, 0) attack_point = to_cp.position.random_point_within(500, 0)
else: else:
attack_point = self.find_offensive_point(dcs_group, forward_heading, AGGRESIVE_MOVE_DISTANCE) attack_point = self.find_offensive_point(dcs_group, forward_heading, AGGRESIVE_MOVE_DISTANCE)
dcs_group.add_waypoint(attack_point, PointAction.OnRoad) dcs_group.add_waypoint(attack_point, PointAction.OffRoad)
if stance != CombatStance.RETREAT: if stance != CombatStance.RETREAT:
self.add_morale_trigger(dcs_group, forward_heading) self.add_morale_trigger(dcs_group, forward_heading)
return True
return False
def plan_action_for_groups(
self, stance: CombatStance,
ally_groups: List[Tuple[VehicleGroup, CombatGroup]],
enemy_groups: List[Tuple[VehicleGroup, CombatGroup]],
forward_heading: int,
from_cp: ControlPoint,
to_cp: ControlPoint
) -> None:
if not self.game.settings.perf_moving_units:
return
for dcs_group, group in ally_groups:
if hasattr(group.units[0], 'eplrs') and group.units[0].eplrs:
dcs_group.points[0].tasks.append(EPLRS(dcs_group.id))
if group.role == CombatGroupRole.ARTILLERY:
if self.game.settings.perf_artillery:
target = self.get_artillery_target_in_range(dcs_group, group, enemy_groups)
if target is not None:
self._plan_artillery_action(stance, group, dcs_group, forward_heading, target)
elif group.role in [CombatGroupRole.TANK, CombatGroupRole.IFV]:
self._plan_tank_ifv_action(stance, enemy_groups, dcs_group, forward_heading, to_cp)
elif group.role in [CombatGroupRole.APC, CombatGroupRole.ATGM]:
self._plan_apc_atgm_action(stance, dcs_group, forward_heading, to_cp)
if stance == CombatStance.RETREAT: if stance == CombatStance.RETREAT:
# In retreat mode, the units will fall back # In retreat mode, the units will fall back
@ -345,10 +422,10 @@ class GroundConflictGenerator:
else: else:
retreat_point = self.find_retreat_point(dcs_group, forward_heading) retreat_point = self.find_retreat_point(dcs_group, forward_heading)
reposition_point = retreat_point.point_from_heading(forward_heading, 10) # Another point to make the unit face the enemy reposition_point = retreat_point.point_from_heading(forward_heading, 10) # Another point to make the unit face the enemy
dcs_group.add_waypoint(retreat_point, PointAction.OnRoad) dcs_group.add_waypoint(retreat_point, PointAction.OffRoad)
dcs_group.add_waypoint(reposition_point, PointAction.OffRoad) dcs_group.add_waypoint(reposition_point, PointAction.OffRoad)
def add_morale_trigger(self, dcs_group, forward_heading): def add_morale_trigger(self, dcs_group: VehicleGroup, forward_heading: int) -> None:
""" """
This add a trigger to manage units fleeing whenever their group is hit hard, or being engaged by CAS This add a trigger to manage units fleeing whenever their group is hit hard, or being engaged by CAS
""" """
@ -365,7 +442,10 @@ class GroundConflictGenerator:
dcs_group.manualHeading = True dcs_group.manualHeading = True
# We add a new retreat waypoint # We add a new retreat waypoint
dcs_group.add_waypoint(self.find_retreat_point(dcs_group, forward_heading, (int)(RETREAT_DISTANCE / 8)), PointAction.OffRoad) dcs_group.add_waypoint(
self.find_retreat_point(dcs_group, forward_heading, (int)(RETREAT_DISTANCE / 8)),
PointAction.OffRoad
)
# Fallback task # Fallback task
fallback = ControlledTask(GoToWaypoint(to_index=len(dcs_group.points))) fallback = ControlledTask(GoToWaypoint(to_index=len(dcs_group.points)))
@ -384,7 +464,12 @@ class GroundConflictGenerator:
self.mission.triggerrules.triggers.append(fallback) self.mission.triggerrules.triggers.append(fallback)
def find_retreat_point(self, dcs_group, frontline_heading, distance=RETREAT_DISTANCE): @staticmethod
def find_retreat_point(
dcs_group: VehicleGroup,
frontline_heading: int,
distance: int = RETREAT_DISTANCE
) -> Point:
""" """
Find a point to retreat to Find a point to retreat to
:param dcs_group: DCS mission group we are searching a retreat point for :param dcs_group: DCS mission group we are searching a retreat point for
@ -393,7 +478,12 @@ class GroundConflictGenerator:
""" """
return dcs_group.points[0].position.point_from_heading(frontline_heading-180, distance) return dcs_group.points[0].position.point_from_heading(frontline_heading-180, distance)
def find_offensive_point(self, dcs_group, frontline_heading, distance): @staticmethod
def find_offensive_point(
dcs_group: VehicleGroup,
frontline_heading: int,
distance: int
) -> Point:
""" """
Find a point to attack Find a point to attack
:param dcs_group: DCS mission group we are searching an attack point for :param dcs_group: DCS mission group we are searching an attack point for
@ -403,24 +493,36 @@ class GroundConflictGenerator:
""" """
return dcs_group.points[0].position.point_from_heading(frontline_heading, distance) return dcs_group.points[0].position.point_from_heading(frontline_heading, distance)
def find_n_nearest_enemy_groups(self, player_group, enemy_groups, n): @staticmethod
def find_n_nearest_enemy_groups(
player_group: VehicleGroup,
enemy_groups: List[Tuple[VehicleGroup, CombatGroup]],
n: int
) -> List[VehicleGroup]:
""" """
Return the neaarest enemy group for the player group Return the nearest enemy group for the player group
@param group Group for which we should find the nearest ennemies @param group Group for which we should find the nearest ennemies
@param enemy_groups Potential enemy groups @param enemy_groups Potential enemy groups
@param n number of nearby groups to take @param n number of nearby groups to take
""" """
targets = [] targets = [] # type: List[Optional[VehicleGroup]]
sorted_list = sorted(enemy_groups, key=lambda group: player_group.points[0].position.distance_to_point(group[0].points[0].position)) sorted_list = sorted(
enemy_groups,
key=lambda group: player_group.points[0].position.distance_to_point(group[0].points[0].position)
)
for i in range(n): for i in range(n):
# TODO: Is this supposed to return no groups if enemy_groups is less than n?
if len(sorted_list) <= i: if len(sorted_list) <= i:
break break
else: else:
targets.append(sorted_list[i][0]) targets.append(sorted_list[i][0])
return targets return targets
@staticmethod
def find_nearest_enemy_group(self, player_group, enemy_groups): def find_nearest_enemy_group(
player_group: VehicleGroup,
enemy_groups: List[Tuple[VehicleGroup, CombatGroup]]
) -> Optional[VehicleGroup]:
""" """
Search the enemy groups for a potential target suitable to armored assault Search the enemy groups for a potential target suitable to armored assault
@param group Group for which we should find the nearest ennemy @param group Group for which we should find the nearest ennemy
@ -428,22 +530,27 @@ class GroundConflictGenerator:
""" """
min_distance = 99999999 min_distance = 99999999
target = None target = None
for dcs_group, group in enemy_groups: for dcs_group, _ in enemy_groups:
dist = player_group.points[0].position.distance_to_point(dcs_group.points[0].position) dist = player_group.points[0].position.distance_to_point(dcs_group.points[0].position)
if dist < min_distance: if dist < min_distance:
min_distance = dist min_distance = dist
target = dcs_group target = dcs_group
return target return target
@staticmethod
def get_artillery_target_in_range(self, dcs_group, group, enemy_groups): def get_artillery_target_in_range(
dcs_group: VehicleGroup,
group: CombatGroup,
enemy_groups: List[Tuple[VehicleGroup, CombatGroup]]
) -> Optional[Point]:
""" """
Search the enemy groups for a potential target suitable to an artillery unit 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 = group.units[0].threat_range
if len(enemy_groups) == 0: if not enemy_groups:
return None return None
for o in range(10): for _ in range(10):
potential_target = random.choice(enemy_groups)[0] potential_target = random.choice(enemy_groups)[0]
distance_to_target = dcs_group.points[0].position.distance_to_point(potential_target.points[0].position) distance_to_target = dcs_group.points[0].position.distance_to_point(potential_target.points[0].position)
if distance_to_target < rng: if distance_to_target < rng:
@ -480,7 +587,12 @@ class GroundConflictGenerator:
continue continue
return None return None
def _generate_groups(self, groups: List[CombatGroup], frontline_vector: Tuple[Point, int, int], is_player: bool): def _generate_groups(
self,
groups: List[CombatGroup],
frontline_vector: Tuple[Point, int, int],
is_player: bool
) -> List[Tuple[VehicleGroup, CombatGroup]]:
"""Finds valid positions for planned groups and generates a pydcs group for them""" """Finds valid positions for planned groups and generates a pydcs group for them"""
positioned_groups = [] positioned_groups = []
position, heading, combat_width = frontline_vector position, heading, combat_width = frontline_vector
@ -513,8 +625,13 @@ class GroundConflictGenerator:
g.set_skill(self.game.settings.player_skill) g.set_skill(self.game.settings.player_skill)
else: else:
g.set_skill(self.game.settings.enemy_vehicle_skill) g.set_skill(self.game.settings.enemy_vehicle_skill)
positioned_groups.append((g,group)) positioned_groups.append((g, group))
self.gen_infantry_group_for_group(g, is_player, self.mission.country(country), opposite_heading(spawn_heading)) self.gen_infantry_group_for_group(
g,
is_player,
self.mission.country(country),
opposite_heading(spawn_heading)
)
else: else:
logging.warning(f"Unable to get valid position for {group}") logging.warning(f"Unable to get valid position for {group}")

View File

@ -1,6 +1,6 @@
import logging import logging
import random import random
from typing import Tuple from typing import Tuple, Optional
from dcs.country import Country from dcs.country import Country
from dcs.mapping import Point from dcs.mapping import Point
@ -22,8 +22,8 @@ class Conflict:
attackers_country: Country, attackers_country: Country,
defenders_country: Country, defenders_country: Country,
position: Point, position: Point,
heading=None, heading: Optional[int] = None,
size=None size: Optional[int] = None
): ):
self.attackers_side = attackers_side self.attackers_side = attackers_side

View File

@ -193,12 +193,9 @@ class TriggersGenerator:
self._set_allegiances(player_coalition, enemy_coalition) self._set_allegiances(player_coalition, enemy_coalition)
self._gen_markers() self._gen_markers()
self._generate_capture_triggers(player_coalition, enemy_coalition) self._generate_capture_triggers(player_coalition, enemy_coalition)
print("Test")
@classmethod @classmethod
def get_capture_zone_flag(cls): def get_capture_zone_flag(cls):
flag = cls.capture_zone_flag flag = cls.capture_zone_flag
cls.capture_zone_flag += 1 cls.capture_zone_flag += 1
return flag return flag