mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
FARP spawn for helis on frontline cas; updated ground object placements
This commit is contained in:
parent
ca521e7e51
commit
d31876b65e
24
game/db.py
24
game/db.py
@ -358,7 +358,8 @@ PLANE_PAYLOAD_OVERRIDES = {
|
||||
},
|
||||
|
||||
Ka_50: {
|
||||
"*": "12x9A4172, 40xS-8",
|
||||
CAS: "12x9A4172, 40xS-8",
|
||||
GroundAttack: "12x9A4172, 40xS-8",
|
||||
},
|
||||
|
||||
M_2000C: {
|
||||
@ -483,6 +484,27 @@ def assigned_units_from(d: PlaneDict) -> AssignedUnitsDict:
|
||||
return {k: (v, 0) for k, v in d.items()}
|
||||
|
||||
|
||||
def assignedunits_split_to_count(dict: AssignedUnitsDict, count: int):
|
||||
buffer_dict = {}
|
||||
for unit_type, (unit_count, client_count) in dict.items():
|
||||
for _ in range(unit_count):
|
||||
new_count, new_client_count = buffer_dict.get(unit_type, (0, 0))
|
||||
|
||||
new_count += 1
|
||||
|
||||
if client_count > 0:
|
||||
new_client_count += 1
|
||||
client_count -= 1
|
||||
|
||||
buffer_dict[unit_type] = new_count, new_client_count
|
||||
if new_count >= count:
|
||||
yield buffer_dict
|
||||
buffer_dict = {}
|
||||
|
||||
if len(buffer_dict):
|
||||
yield buffer_dict
|
||||
|
||||
|
||||
def unitdict_from(fd: AssignedUnitsDict) -> Dict:
|
||||
return {k: v1 for k, (v1, v2) in fd.items()}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import typing
|
||||
import logging
|
||||
|
||||
from dcs.unittype import UnitType
|
||||
from dcs.task import Task
|
||||
from dcs.task import *
|
||||
from dcs.unittype import UnitType
|
||||
|
||||
from game import *
|
||||
|
||||
@ -39,12 +39,15 @@ class FrontlineAttackOperation(Operation):
|
||||
def generate(self):
|
||||
self.armorgen.generate_vec(self.attackers, self.target)
|
||||
|
||||
planes_flights = {k: v for k, v in self.strikegroup.items() if k in plane_map}
|
||||
planes_flights = {k: v for k, v in self.strikegroup.items() if k in plane_map.values()}
|
||||
self.airgen.generate_cas_strikegroup(*assigned_units_split(planes_flights), at=self.attackers_starting_position)
|
||||
|
||||
heli_flights = {k: v for k, v in self.strikegroup.items() if k in helicopters.helicopter_map}
|
||||
heli_flights = {k: v for k, v in self.strikegroup.items() if k in helicopters.helicopter_map.values()}
|
||||
if heli_flights:
|
||||
self.airgen.generate_cas_strikegroup(*assigned_units_split(heli_flights), at=self.groundobjectgen.generate_farp())
|
||||
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_cas_strikegroup(*assigned_units_split(dict), at=farp, escort=False)
|
||||
|
||||
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."
|
||||
|
||||
@ -5,6 +5,7 @@ from dcs.mission import *
|
||||
|
||||
DISTANCE_FACTOR = 0.5, 1
|
||||
EXTRA_AA_MIN_DISTANCE = 35000
|
||||
EXTRA_AA_MAX_DISTANCE = 150000
|
||||
EXTRA_AA_POSITION_FROM_CP = 550
|
||||
|
||||
|
||||
@ -58,7 +59,9 @@ class ExtraAAConflictGenerator:
|
||||
if cp.position.distance_to_point(self.conflict.from_cp.position) < EXTRA_AA_MIN_DISTANCE:
|
||||
continue
|
||||
|
||||
print("generated extra aa for {}".format(cp))
|
||||
if cp.position.distance_to_point(self.conflict.position) > EXTRA_AA_MAX_DISTANCE:
|
||||
continue
|
||||
|
||||
country_name = cp.captured and self.player_name or self.enemy_name
|
||||
position = cp.position.point_from_heading(0, EXTRA_AA_POSITION_FROM_CP)
|
||||
|
||||
|
||||
@ -112,6 +112,7 @@ class AircraftConflictGenerator:
|
||||
group.units[idx].set_client()
|
||||
|
||||
group.points[0].tasks.append(OptReactOnThreat(OptReactOnThreat.Values.EvadeFire))
|
||||
group.set_frequency(251.0)
|
||||
|
||||
def _generate_at_airport(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, airport: Airport = None) -> FlyingGroup:
|
||||
assert count > 0
|
||||
@ -155,11 +156,11 @@ class AircraftConflictGenerator:
|
||||
start_type=self._start_type(),
|
||||
group_size=count)
|
||||
|
||||
def _generate_at_carrier(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: ShipGroup) -> FlyingGroup:
|
||||
def _generate_at_group(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: typing.Union[ShipGroup, StaticGroup]) -> FlyingGroup:
|
||||
assert count > 0
|
||||
assert unit is not None
|
||||
|
||||
logging.info("airgen: {} for {} at carrier {}".format(unit_type, side.id, at))
|
||||
logging.info("airgen: {} for {} at unit {}".format(unit_type, side.id, at))
|
||||
return self.m.flight_group_from_unit(
|
||||
country=side,
|
||||
name=name,
|
||||
@ -172,10 +173,10 @@ class AircraftConflictGenerator:
|
||||
def _generate_group(self, name: str, side: Country, unit_type: FlyingType, count: int, client_count: int, at: db.StartingPosition):
|
||||
if isinstance(at, Point):
|
||||
return self._generate_inflight(name, side, unit_type, count, client_count, at)
|
||||
elif isinstance(at, ShipGroup):
|
||||
elif isinstance(at, Group):
|
||||
takeoff_ban = unit_type in db.CARRIER_TAKEOFF_BAN
|
||||
if not takeoff_ban:
|
||||
return self._generate_at_carrier(name, side, unit_type, count, client_count, at)
|
||||
return self._generate_at_group(name, side, unit_type, count, client_count, at)
|
||||
else:
|
||||
return self._generate_inflight(name, side, unit_type, count, client_count, at.position)
|
||||
elif issubclass(at, Airport):
|
||||
@ -192,14 +193,16 @@ class AircraftConflictGenerator:
|
||||
assert False
|
||||
|
||||
def _rtb_for(self, group: FlyingGroup, cp: ControlPoint, at: db.StartingPosition = None):
|
||||
group.add_waypoint(cp.position, RTB_ALTITUDE)
|
||||
if not at:
|
||||
at = cp.at
|
||||
|
||||
if isinstance(cp.at, Point):
|
||||
pass
|
||||
elif isinstance(cp.at, ShipGroup):
|
||||
pass
|
||||
elif issubclass(cp.at, Airport):
|
||||
group.land_at(cp.at)
|
||||
if isinstance(at, Point):
|
||||
group.add_waypoint(at, RTB_ALTITUDE)
|
||||
elif isinstance(at, Group):
|
||||
group.add_waypoint(at.position, RTB_ALTITUDE)
|
||||
elif issubclass(at, Airport):
|
||||
group.add_waypoint(at.position, RTB_ALTITUDE)
|
||||
group.land_at(at)
|
||||
|
||||
def _at_position(self, at) -> Point:
|
||||
if isinstance(at, Point):
|
||||
@ -243,8 +246,8 @@ class AircraftConflictGenerator:
|
||||
groups.append(group)
|
||||
return groups
|
||||
|
||||
def generate_cas_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
assert len(self.escort_targets) == 0
|
||||
def generate_cas_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None, escort=True):
|
||||
assert not escort or len(self.escort_targets) == 0
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(attackers, clients):
|
||||
group = self._generate_group(
|
||||
@ -261,11 +264,12 @@ class AircraftConflictGenerator:
|
||||
|
||||
group.task = CAS.name
|
||||
self._setup_group(group, CAS, client_count)
|
||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||
self._rtb_for(group, self.conflict.from_cp, at)
|
||||
|
||||
def generate_ground_attack_strikegroup(self, strikegroup: db.PlaneDict, clients: db.PlaneDict, targets: typing.List[typing.Tuple[str, Point]], at: db.StartingPosition = None):
|
||||
assert len(self.escort_targets) == 0
|
||||
def generate_ground_attack_strikegroup(self, strikegroup: db.PlaneDict, clients: db.PlaneDict, targets: typing.List[typing.Tuple[str, Point]], at: db.StartingPosition = None, 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(
|
||||
@ -285,11 +289,12 @@ class AircraftConflictGenerator:
|
||||
|
||||
group.task = GroundAttack.name
|
||||
self._setup_group(group, GroundAttack, client_count)
|
||||
self.escort_targets.append((group, group.points.index(escort_until_waypoint)))
|
||||
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):
|
||||
assert len(self.escort_targets) == 0
|
||||
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
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(defenders, clients):
|
||||
group = self._generate_group(
|
||||
@ -310,11 +315,12 @@ class AircraftConflictGenerator:
|
||||
|
||||
group.task = CAS.name
|
||||
self._setup_group(group, CAS, client_count)
|
||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||
self._rtb_for(group, self.conflict.to_cp, at)
|
||||
|
||||
def generate_ship_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, target_groups: typing.Collection[ShipGroup], at: db.StartingPosition = None):
|
||||
assert len(self.escort_targets) == 0
|
||||
def generate_ship_strikegroup(self, attackers: db.PlaneDict, clients: db.PlaneDict, target_groups: typing.Collection[ShipGroup], at: db.StartingPosition = None, escort=True):
|
||||
assert not escort or len(self.escort_targets) == 0
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(attackers, clients):
|
||||
group = self._generate_group(
|
||||
@ -331,7 +337,8 @@ class AircraftConflictGenerator:
|
||||
|
||||
group.task = AntishipStrike.name
|
||||
self._setup_group(group, AntishipStrike, client_count)
|
||||
self.escort_targets.append((group, group.points.index(wayp)))
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(wayp)))
|
||||
self._rtb_for(group, self.conflict.from_cp, at)
|
||||
|
||||
def generate_attackers_escort(self, attackers: db.PlaneDict, clients: db.PlaneDict, at: db.StartingPosition = None):
|
||||
@ -413,8 +420,8 @@ class AircraftConflictGenerator:
|
||||
self._setup_group(group, CAP, client_count)
|
||||
self._rtb_for(group, self.conflict.to_cp, at)
|
||||
|
||||
def generate_transport(self, transport: db.PlaneDict, destination: Airport):
|
||||
assert len(self.escort_targets) == 0
|
||||
def generate_transport(self, transport: db.PlaneDict, destination: Airport, escort=True):
|
||||
assert not escort or len(self.escort_targets) == 0
|
||||
|
||||
for flying_type, count, client_count in self._split_to_groups(transport):
|
||||
group = self._generate_group(
|
||||
@ -426,8 +433,8 @@ class AircraftConflictGenerator:
|
||||
at=self._group_point(self.conflict.air_defenders_location))
|
||||
|
||||
waypoint = group.add_waypoint(destination.position.random_point_within(0, 0), TRANSPORT_LANDING_ALT)
|
||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||
|
||||
if escort:
|
||||
self.escort_targets.append((group, group.points.index(waypoint)))
|
||||
group.task = Transport.name
|
||||
group.land_at(destination)
|
||||
|
||||
|
||||
@ -22,21 +22,26 @@ CATEGORY_MAPPING = {
|
||||
|
||||
|
||||
class GroundObjectsGenerator:
|
||||
FARP_CAPACITY = 4
|
||||
|
||||
def __init__(self, mission: Mission, conflict: Conflict, game):
|
||||
self.m = mission
|
||||
self.conflict = conflict
|
||||
self.game = game
|
||||
|
||||
def generate_farp(self) -> 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!"
|
||||
|
||||
position = self.conflict.find_ground_position(self.conflict.center.point_from_heading(self.conflict.opposite_heading, FARP_FRONTLINE_DISTANCE))
|
||||
return self.m.static_group(
|
||||
country=self.m.country(self.game.player),
|
||||
name="",
|
||||
_type=Fortification.FARP_Command_Post,
|
||||
position=position
|
||||
)
|
||||
for i, _ in enumerate(range(0, number_of_units, self.FARP_CAPACITY)):
|
||||
heading = self.conflict.heading - 90
|
||||
position = self.conflict.find_ground_position(self.conflict.center.point_from_heading(heading, FARP_FRONTLINE_DISTANCE), heading)
|
||||
position = position.point_from_heading(0, i * 275)
|
||||
|
||||
yield self.m.farp(
|
||||
country=self.m.country(self.game.player),
|
||||
name="FARP",
|
||||
position=position,
|
||||
)
|
||||
|
||||
def generate(self):
|
||||
side = self.m.country(self.game.enemy)
|
||||
|
||||
@ -72,32 +72,35 @@ class TriggersGenerator:
|
||||
for coalition_name, coalition in self.mission.coalition.items():
|
||||
for country in coalition.countries.values():
|
||||
if coalition_name == player_coalition:
|
||||
for plane_group in country.plane_group + country.helicopter_group:
|
||||
if plane_group.task == AWACS.name or plane_group.task == Refueling.name:
|
||||
for group in country.plane_group + country.helicopter_group:
|
||||
if group.task == AWACS.name or group.task == Refueling.name:
|
||||
continue
|
||||
|
||||
if player_cp.position.distance_to_point(group.position) > PUSH_TRIGGER_SIZE * 3:
|
||||
continue
|
||||
|
||||
regroup_heading = self.conflict.to_cp.position.heading_between_point(player_cp.position)
|
||||
|
||||
pos1 = plane_group.position.point_from_heading(regroup_heading, REGROUP_ZONE_DISTANCE)
|
||||
pos2 = plane_group.position.point_from_heading(regroup_heading, REGROUP_ZONE_DISTANCE+5000)
|
||||
w1 = plane_group.add_waypoint(pos1, REGROUP_ALT)
|
||||
w2 = plane_group.add_waypoint(pos2, REGROUP_ALT)
|
||||
pos1 = group.position.point_from_heading(regroup_heading, REGROUP_ZONE_DISTANCE)
|
||||
pos2 = group.position.point_from_heading(regroup_heading, REGROUP_ZONE_DISTANCE+5000)
|
||||
w1 = group.add_waypoint(pos1, REGROUP_ALT)
|
||||
w2 = group.add_waypoint(pos2, REGROUP_ALT)
|
||||
|
||||
plane_group.points.remove(w1)
|
||||
plane_group.points.remove(w2)
|
||||
group.points.remove(w1)
|
||||
group.points.remove(w2)
|
||||
|
||||
plane_group.points.insert(1, w2)
|
||||
plane_group.points.insert(1, w1)
|
||||
group.points.insert(1, w2)
|
||||
group.points.insert(1, w1)
|
||||
|
||||
w1.tasks.append(Silence(True))
|
||||
|
||||
switch_waypoint_task = ControlledTask(SwitchWaypoint(from_waypoint=3, to_waypoint=2))
|
||||
switch_waypoint_task.start_if_user_flag(1, False)
|
||||
w2.tasks.append(switch_waypoint_task)
|
||||
plane_group.points[3].tasks.append(Silence(False))
|
||||
group.points[3].tasks.append(Silence(False))
|
||||
|
||||
plane_group.add_trigger_action(SwitchWaypoint(to_waypoint=4))
|
||||
push_by_trigger.append(plane_group)
|
||||
group.add_trigger_action(SwitchWaypoint(to_waypoint=4))
|
||||
push_by_trigger.append(group)
|
||||
|
||||
push_trigger_zone = self.mission.triggers.add_triggerzone(player_cp.position, PUSH_TRIGGER_SIZE, name="Push zone")
|
||||
push_trigger = TriggerOnce(Event.NoEvent, "Push trigger")
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user