mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
special flight for AI to SEAD; AI bomb task
This commit is contained in:
parent
b697a8b40a
commit
c7c2b9a248
@ -380,7 +380,7 @@ PLANE_PAYLOAD_OVERRIDES = {
|
|||||||
CAP: "AIM-54A-MK47*4, AIM-7M*2, AIM-9M*2, XT*2",
|
CAP: "AIM-54A-MK47*4, AIM-7M*2, AIM-9M*2, XT*2",
|
||||||
Escort: "AIM-54A-MK47*4, AIM-7M*2, AIM-9M*2, XT*2",
|
Escort: "AIM-54A-MK47*4, AIM-7M*2, AIM-9M*2, XT*2",
|
||||||
CAS: "AIM-54A-MK60*1, AIM-7M*1, AIM-9M*2, XT*2, Mk-82*2, LANTIRN",
|
CAS: "AIM-54A-MK60*1, AIM-7M*1, AIM-9M*2, XT*2, Mk-82*2, LANTIRN",
|
||||||
GroundAttack: "AIM-54A-MK60*1, AIM-7M*1, AIM-9M*2, XT*2, Mk-82*2, LANTIRN",
|
GroundAttack: "AIM54, AIM-9M*2, XT*2, GBU-12*4, LANTIRN",
|
||||||
},
|
},
|
||||||
|
|
||||||
Su_25T: {
|
Su_25T: {
|
||||||
|
|||||||
@ -71,6 +71,10 @@ class Event:
|
|||||||
def ai_banned_tasks(self) -> typing.Collection[typing.Type[Task]]:
|
def ai_banned_tasks(self) -> typing.Collection[typing.Type[Task]]:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def player_banned_tasks(self) -> typing.Collection[typing.Type[Task]]:
|
||||||
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def global_cp_available(self) -> bool:
|
def global_cp_available(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|||||||
@ -20,7 +20,7 @@ class StrikeEvent(Event):
|
|||||||
@property
|
@property
|
||||||
def tasks(self):
|
def tasks(self):
|
||||||
if self.is_player_attacking:
|
if self.is_player_attacking:
|
||||||
return [CAP, CAS]
|
return [CAP, CAS, SEAD]
|
||||||
else:
|
else:
|
||||||
return [CAP]
|
return [CAP]
|
||||||
|
|
||||||
@ -28,6 +28,10 @@ class StrikeEvent(Event):
|
|||||||
def ai_banned_tasks(self):
|
def ai_banned_tasks(self):
|
||||||
return [CAS]
|
return [CAS]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def player_banned_tasks(self):
|
||||||
|
return [SEAD]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def global_cp_available(self) -> bool:
|
def global_cp_available(self) -> bool:
|
||||||
return True
|
return True
|
||||||
@ -38,6 +42,8 @@ class StrikeEvent(Event):
|
|||||||
return "Escort flight"
|
return "Escort flight"
|
||||||
else:
|
else:
|
||||||
return "CAP flight"
|
return "CAP flight"
|
||||||
|
elif for_task == SEAD:
|
||||||
|
return "SEAD flight"
|
||||||
elif for_task == CAS:
|
elif for_task == CAS:
|
||||||
return "Strike flight"
|
return "Strike flight"
|
||||||
|
|
||||||
@ -47,7 +53,7 @@ class StrikeEvent(Event):
|
|||||||
self.to_cp.base.affect_strength(-self.SINGLE_OBJECT_STRENGTH_INFLUENCE * len(debriefing.destroyed_objects))
|
self.to_cp.base.affect_strength(-self.SINGLE_OBJECT_STRENGTH_INFLUENCE * len(debriefing.destroyed_objects))
|
||||||
|
|
||||||
def player_attacking(self, flights: db.TaskForceDict):
|
def player_attacking(self, flights: db.TaskForceDict):
|
||||||
assert CAP in flights and CAS in flights and len(flights) == 2, "Invalid flights"
|
assert CAP in flights and CAS in flights and SEAD in flights and len(flights) == 3, "Invalid flights"
|
||||||
|
|
||||||
op = StrikeOperation(
|
op = StrikeOperation(
|
||||||
self.game,
|
self.game,
|
||||||
@ -60,6 +66,7 @@ class StrikeEvent(Event):
|
|||||||
|
|
||||||
interceptors = self.to_cp.base.scramble_interceptors(self.game.settings.multiplier)
|
interceptors = self.to_cp.base.scramble_interceptors(self.game.settings.multiplier)
|
||||||
op.setup(strikegroup=flights[CAS],
|
op.setup(strikegroup=flights[CAS],
|
||||||
|
sead=flights[SEAD],
|
||||||
escort=flights[CAP],
|
escort=flights[CAP],
|
||||||
interceptors=assigned_units_from(interceptors))
|
interceptors=assigned_units_from(interceptors))
|
||||||
|
|
||||||
|
|||||||
@ -99,15 +99,14 @@ class Operation:
|
|||||||
self.defenders_starting_position = self.to_cp.at
|
self.defenders_starting_position = self.to_cp.at
|
||||||
|
|
||||||
def prepare_carriers(self, for_units: db.UnitsDict):
|
def prepare_carriers(self, for_units: db.UnitsDict):
|
||||||
for global_cp in self.game.theater.controlpoints:
|
if not self.departure_cp.is_global:
|
||||||
if not global_cp.is_global:
|
return
|
||||||
continue
|
|
||||||
|
|
||||||
ship = self.shipgen.generate_carrier(for_units=[t for t, c in for_units.items() if c > 0],
|
ship = self.shipgen.generate_carrier(for_units=[t for t, c in for_units.items() if c > 0],
|
||||||
country=self.game.player,
|
country=self.game.player,
|
||||||
at=global_cp.at)
|
at=self.departure_cp.at)
|
||||||
|
|
||||||
if global_cp == self.departure_cp and not self.is_quick:
|
if not self.is_quick:
|
||||||
if not self.to_cp.captured:
|
if not self.to_cp.captured:
|
||||||
self.attackers_starting_position = ship
|
self.attackers_starting_position = ship
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -5,6 +5,7 @@ from .operation import *
|
|||||||
|
|
||||||
class StrikeOperation(Operation):
|
class StrikeOperation(Operation):
|
||||||
strikegroup = None # type: db.AssignedUnitsDict
|
strikegroup = None # type: db.AssignedUnitsDict
|
||||||
|
sead = None # type: db.AssignedUnitsDict
|
||||||
escort = None # type: db.AssignedUnitsDict
|
escort = None # type: db.AssignedUnitsDict
|
||||||
interceptors = None # type: db.AssignedUnitsDict
|
interceptors = None # type: db.AssignedUnitsDict
|
||||||
|
|
||||||
@ -12,9 +13,11 @@ class StrikeOperation(Operation):
|
|||||||
|
|
||||||
def setup(self,
|
def setup(self,
|
||||||
strikegroup: db.AssignedUnitsDict,
|
strikegroup: db.AssignedUnitsDict,
|
||||||
|
sead: db.AssignedUnitsDict,
|
||||||
escort: db.AssignedUnitsDict,
|
escort: db.AssignedUnitsDict,
|
||||||
interceptors: db.AssignedUnitsDict):
|
interceptors: db.AssignedUnitsDict):
|
||||||
self.strikegroup = strikegroup
|
self.strikegroup = strikegroup
|
||||||
|
self.sead = sead
|
||||||
self.escort = escort
|
self.escort = escort
|
||||||
self.interceptors = interceptors
|
self.interceptors = interceptors
|
||||||
|
|
||||||
@ -40,8 +43,10 @@ class StrikeOperation(Operation):
|
|||||||
self.prepare_carriers(db.unitdict_merge(db.unitdict_from(self.strikegroup), db.unitdict_from(self.escort)))
|
self.prepare_carriers(db.unitdict_merge(db.unitdict_from(self.strikegroup), db.unitdict_from(self.escort)))
|
||||||
|
|
||||||
targets = [] # type: typing.List[typing.Tuple[str, str, Point]]
|
targets = [] # type: typing.List[typing.Tuple[str, str, Point]]
|
||||||
|
sead_targets = [] # type: typing.List[typing.Tuple[str, str, Point]]
|
||||||
category_counters = {} # type: typing.Dict[str, int]
|
category_counters = {} # type: typing.Dict[str, int]
|
||||||
processed_groups = []
|
processed_groups = []
|
||||||
|
|
||||||
for object in self.to_cp.ground_objects:
|
for object in self.to_cp.ground_objects:
|
||||||
if object.group_identifier in processed_groups:
|
if object.group_identifier in processed_groups:
|
||||||
continue
|
continue
|
||||||
@ -49,6 +54,10 @@ class StrikeOperation(Operation):
|
|||||||
processed_groups.append(object.group_identifier)
|
processed_groups.append(object.group_identifier)
|
||||||
category_counters[object.category] = category_counters.get(object.category, 0) + 1
|
category_counters[object.category] = category_counters.get(object.category, 0) + 1
|
||||||
markpoint_name = "{}{}".format(object.name_abbrev, category_counters[object.category])
|
markpoint_name = "{}{}".format(object.name_abbrev, category_counters[object.category])
|
||||||
|
|
||||||
|
if object.category == "aa":
|
||||||
|
sead_targets.append((str(object), markpoint_name, object.position))
|
||||||
|
|
||||||
targets.append((str(object), markpoint_name, object.position))
|
targets.append((str(object), markpoint_name, object.position))
|
||||||
|
|
||||||
targets.sort(key=lambda x: self.from_cp.position.distance_to_point(x[2]))
|
targets.sort(key=lambda x: self.from_cp.position.distance_to_point(x[2]))
|
||||||
@ -59,7 +68,13 @@ class StrikeOperation(Operation):
|
|||||||
planes_flights = {k: v for k, v in self.strikegroup.items() if k in plane_map.values()}
|
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),
|
self.airgen.generate_ground_attack_strikegroup(*assigned_units_split(planes_flights),
|
||||||
targets=[(mp, pos) for (n, mp, pos) in targets],
|
targets=[(mp, pos) for (n, mp, pos) in targets],
|
||||||
at=self.attackers_starting_position)
|
at=self.attackers_starting_position,
|
||||||
|
escort=True)
|
||||||
|
|
||||||
|
self.airgen.generate_sead_strikegroup(*assigned_units_split(self.sead),
|
||||||
|
targets=[(mp, pos) for (n, mp, pos) in sead_targets],
|
||||||
|
at=self.attackers_starting_position,
|
||||||
|
escort=False)
|
||||||
|
|
||||||
heli_flights = {k: v for k, v in self.strikegroup.items() if k in helicopters.helicopter_map.values()}
|
heli_flights = {k: v for k, v in self.strikegroup.items() if k in helicopters.helicopter_map.values()}
|
||||||
if heli_flights:
|
if heli_flights:
|
||||||
|
|||||||
@ -309,6 +309,7 @@ class AircraftConflictGenerator:
|
|||||||
|
|
||||||
for name, pos in targets:
|
for name, pos in targets:
|
||||||
waypoint = group.add_waypoint(pos, 0, WARM_START_AIRSPEED, self.m.translation.create_string(name))
|
waypoint = group.add_waypoint(pos, 0, WARM_START_AIRSPEED, self.m.translation.create_string(name))
|
||||||
|
waypoint.tasks.append(Bombing(pos, attack_qty=2))
|
||||||
if escort_until_waypoint is None:
|
if escort_until_waypoint is None:
|
||||||
escort_until_waypoint = waypoint
|
escort_until_waypoint = waypoint
|
||||||
|
|
||||||
@ -318,6 +319,32 @@ class AircraftConflictGenerator:
|
|||||||
self.escort_targets.append((group, group.points.index(escort_until_waypoint)))
|
self.escort_targets.append((group, group.points.index(escort_until_waypoint)))
|
||||||
self._rtb_for(group, self.conflict.from_cp, at)
|
self._rtb_for(group, self.conflict.from_cp, at)
|
||||||
|
|
||||||
|
def generate_sead_strikegroup(self, strikegroup: db.PlaneDict, clients: db.PlaneDict, targets: typing.List[typing.Tuple[str, Point]], at: db.StartingPosition, escort=True):
|
||||||
|
assert not escort or len(self.escort_targets) == 0
|
||||||
|
|
||||||
|
for flying_type, count, client_count in self._split_to_groups(strikegroup, clients):
|
||||||
|
group = self._generate_group(
|
||||||
|
name=namegen.next_unit_name(self.conflict.attackers_side, flying_type),
|
||||||
|
side=self.conflict.attackers_side,
|
||||||
|
unit_type=flying_type,
|
||||||
|
count=count,
|
||||||
|
client_count=client_count,
|
||||||
|
at=at and at or self._group_point(self.conflict.air_attackers_location))
|
||||||
|
|
||||||
|
escort_until_waypoint = None
|
||||||
|
|
||||||
|
for name, pos in targets:
|
||||||
|
waypoint = group.add_waypoint(pos, 0, WARM_START_AIRSPEED, self.m.translation.create_string(name))
|
||||||
|
if escort_until_waypoint is None:
|
||||||
|
escort_until_waypoint = waypoint
|
||||||
|
|
||||||
|
group.task = SEAD.name
|
||||||
|
self._setup_group(group, SEAD, client_count)
|
||||||
|
if escort:
|
||||||
|
self.escort_targets.append((group, group.points.index(escort_until_waypoint)))
|
||||||
|
|
||||||
|
self._rtb_for(group, self.conflict.from_cp, at)
|
||||||
|
|
||||||
def generate_defenders_cas(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None, escort=True):
|
def generate_defenders_cas(self, defenders: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None, escort=True):
|
||||||
assert not escort or len(self.escort_targets) == 0
|
assert not escort or len(self.escort_targets) == 0
|
||||||
|
|
||||||
|
|||||||
@ -26,9 +26,9 @@ WEATHER_FOG_VISIBILITY = 2500, 5000
|
|||||||
WEATHER_FOG_THICKNESS = 100, 500
|
WEATHER_FOG_THICKNESS = 100, 500
|
||||||
|
|
||||||
RANDOM_TIME = {
|
RANDOM_TIME = {
|
||||||
"night": 5,
|
"night": 7,
|
||||||
"dusk": 30,
|
"dusk": 40,
|
||||||
"dawn": 30,
|
"dawn": 40,
|
||||||
"day": 100,
|
"day": 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -79,7 +79,7 @@ def generate_groundobjects(theater: ConflictTheater):
|
|||||||
if not cp.has_frontline:
|
if not cp.has_frontline:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
amount = random.randrange(5, 6)
|
amount = random.randrange(5, 7)
|
||||||
for i in range(0, amount):
|
for i in range(0, amount):
|
||||||
available_categories = list(tpls)
|
available_categories = list(tpls)
|
||||||
if i >= amount - 1:
|
if i >= amount - 1:
|
||||||
|
|||||||
@ -194,6 +194,11 @@ class EventMenu(Menu):
|
|||||||
self.error_label["text"] = "Need at least one player in flight {}".format(self.event.flight_name(task))
|
self.error_label["text"] = "Need at least one player in flight {}".format(self.event.flight_name(task))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
for task in self.event.player_banned_tasks:
|
||||||
|
if tasks_clients_counts.get(task, 0) != 0:
|
||||||
|
self.error_label["text"] = "Players are not allowed on flight {}".format(self.event.flight_name(task))
|
||||||
|
return
|
||||||
|
|
||||||
if self.game.is_player_attack(self.event):
|
if self.game.is_player_attack(self.event):
|
||||||
if isinstance(self.event, FrontlineAttackEvent) or isinstance(self.event, FrontlinePatrolEvent):
|
if isinstance(self.event, FrontlineAttackEvent) or isinstance(self.event, FrontlinePatrolEvent):
|
||||||
if self.event.from_cp.base.total_armor == 0:
|
if self.event.from_cp.base.total_armor == 0:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user