mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
parent
d26fc84316
commit
c37c56c879
@ -7,6 +7,7 @@ from typing import Any, List, Optional, TYPE_CHECKING
|
|||||||
from dcs import Point
|
from dcs import Point
|
||||||
from dcs.planes import C_101CC, C_101EB, Su_33, FA_18C_hornet
|
from dcs.planes import C_101CC, C_101EB, Su_33, FA_18C_hornet
|
||||||
|
|
||||||
|
from pydcs_extensions.hercules.hercules import Hercules
|
||||||
from .flightroster import FlightRoster
|
from .flightroster import FlightRoster
|
||||||
from .flightstate import FlightState, Navigating, Uninitialized
|
from .flightstate import FlightState, Navigating, Uninitialized
|
||||||
from .flightstate.killed import Killed
|
from .flightstate.killed import Killed
|
||||||
@ -18,9 +19,9 @@ from ..sidc import (
|
|||||||
Status,
|
Status,
|
||||||
SymbolSet,
|
SymbolSet,
|
||||||
)
|
)
|
||||||
|
from game.dcs.aircrafttype import AircraftType
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game.dcs.aircrafttype import AircraftType
|
|
||||||
from game.sim.gameupdateevents import GameUpdateEvents
|
from game.sim.gameupdateevents import GameUpdateEvents
|
||||||
from game.sim.simulationresults import SimulationResults
|
from game.sim.simulationresults import SimulationResults
|
||||||
from game.squadrons import Squadron, Pilot
|
from game.squadrons import Squadron, Pilot
|
||||||
@ -161,6 +162,10 @@ class Flight(SidcDescribable):
|
|||||||
def is_helo(self) -> bool:
|
def is_helo(self) -> bool:
|
||||||
return self.unit_type.dcs_unit_type.helicopter
|
return self.unit_type.dcs_unit_type.helicopter
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_hercules(self) -> bool:
|
||||||
|
return self.unit_type == AircraftType.named("C-130J-30 Super Hercules")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def from_cp(self) -> ControlPoint:
|
def from_cp(self) -> ControlPoint:
|
||||||
return self.departure
|
return self.departure
|
||||||
@ -197,6 +202,8 @@ class Flight(SidcDescribable):
|
|||||||
return Su_33.fuel_max * 0.8
|
return Su_33.fuel_max * 0.8
|
||||||
elif unit_type in {C_101EB, C_101CC}:
|
elif unit_type in {C_101EB, C_101CC}:
|
||||||
return unit_type.fuel_max * 0.5
|
return unit_type.fuel_max * 0.5
|
||||||
|
elif unit_type == Hercules:
|
||||||
|
return unit_type.fuel_max * 0.75
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
|
|||||||
@ -25,7 +25,7 @@ class AirAssaultLayout(StandardLayout):
|
|||||||
pickup: FlightWaypoint | None
|
pickup: FlightWaypoint | None
|
||||||
nav_to_ingress: list[FlightWaypoint]
|
nav_to_ingress: list[FlightWaypoint]
|
||||||
ingress: FlightWaypoint
|
ingress: FlightWaypoint
|
||||||
drop_off: FlightWaypoint
|
drop_off: FlightWaypoint | None
|
||||||
# This is an implementation detail used by CTLD. The aircraft will not go to this
|
# This is an implementation detail used by CTLD. The aircraft will not go to this
|
||||||
# waypoint. It is used by CTLD as the destination for unloaded troops.
|
# waypoint. It is used by CTLD as the destination for unloaded troops.
|
||||||
target: FlightWaypoint
|
target: FlightWaypoint
|
||||||
@ -37,7 +37,8 @@ class AirAssaultLayout(StandardLayout):
|
|||||||
yield self.pickup
|
yield self.pickup
|
||||||
yield from self.nav_to_ingress
|
yield from self.nav_to_ingress
|
||||||
yield self.ingress
|
yield self.ingress
|
||||||
yield self.drop_off
|
if self.drop_off is not None:
|
||||||
|
yield self.drop_off
|
||||||
yield self.target
|
yield self.target
|
||||||
yield from self.nav_to_home
|
yield from self.nav_to_home
|
||||||
yield self.arrival
|
yield self.arrival
|
||||||
@ -53,7 +54,9 @@ class AirAssaultFlightPlan(StandardFlightPlan[AirAssaultLayout], UiZoneDisplay):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def tot_waypoint(self) -> FlightWaypoint:
|
def tot_waypoint(self) -> FlightWaypoint:
|
||||||
return self.layout.drop_off
|
if self.flight.is_helo and self.layout.drop_off is not None:
|
||||||
|
return self.layout.drop_off
|
||||||
|
return self.layout.target
|
||||||
|
|
||||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||||
if waypoint == self.tot_waypoint:
|
if waypoint == self.tot_waypoint:
|
||||||
@ -80,8 +83,10 @@ class AirAssaultFlightPlan(StandardFlightPlan[AirAssaultLayout], UiZoneDisplay):
|
|||||||
|
|
||||||
class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
|
class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
|
||||||
def layout(self) -> AirAssaultLayout:
|
def layout(self) -> AirAssaultLayout:
|
||||||
if not self.flight.is_helo:
|
if not self.flight.is_helo and not self.flight.is_hercules:
|
||||||
raise PlanningError("Air assault is only usable by helicopters")
|
raise PlanningError(
|
||||||
|
"Air assault is only usable by helicopters and Anubis' C-130 mod"
|
||||||
|
)
|
||||||
assert self.package.waypoints is not None
|
assert self.package.waypoints is not None
|
||||||
|
|
||||||
altitude = feet(1500) if self.flight.is_helo else self.doctrine.ingress_altitude
|
altitude = feet(1500) if self.flight.is_helo else self.doctrine.ingress_altitude
|
||||||
@ -89,7 +94,7 @@ class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
|
|||||||
|
|
||||||
builder = WaypointBuilder(self.flight, self.coalition)
|
builder = WaypointBuilder(self.flight, self.coalition)
|
||||||
|
|
||||||
if self.flight.departure.cptype in [
|
if self.flight.is_hercules or self.flight.departure.cptype in [
|
||||||
ControlPointType.AIRCRAFT_CARRIER_GROUP,
|
ControlPointType.AIRCRAFT_CARRIER_GROUP,
|
||||||
ControlPointType.LHA_GROUP,
|
ControlPointType.LHA_GROUP,
|
||||||
ControlPointType.OFF_MAP,
|
ControlPointType.OFF_MAP,
|
||||||
@ -114,12 +119,15 @@ class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
|
|||||||
pickup_position = pickup.position
|
pickup_position = pickup.position
|
||||||
assault_area = builder.assault_area(self.package.target)
|
assault_area = builder.assault_area(self.package.target)
|
||||||
heading = self.package.target.position.heading_between_point(pickup_position)
|
heading = self.package.target.position.heading_between_point(pickup_position)
|
||||||
|
if self.flight.is_hercules:
|
||||||
|
assault_area.only_for_player = False
|
||||||
|
|
||||||
# TODO we can not gurantee a safe LZ for DropOff. See comment above.
|
# TODO we can not gurantee a safe LZ for DropOff. See comment above.
|
||||||
drop_off_zone = MissionTarget(
|
drop_off_zone = MissionTarget(
|
||||||
"Dropoff zone",
|
"Dropoff zone",
|
||||||
self.package.target.position.point_from_heading(heading, 1200),
|
self.package.target.position.point_from_heading(heading, 1200),
|
||||||
)
|
)
|
||||||
|
dz = builder.dropoff_zone(drop_off_zone) if self.flight.is_helo else None
|
||||||
|
|
||||||
return AirAssaultLayout(
|
return AirAssaultLayout(
|
||||||
departure=builder.takeoff(self.flight.departure),
|
departure=builder.takeoff(self.flight.departure),
|
||||||
@ -135,7 +143,7 @@ class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
|
|||||||
self.package.waypoints.ingress,
|
self.package.waypoints.ingress,
|
||||||
self.package.target,
|
self.package.target,
|
||||||
),
|
),
|
||||||
drop_off=builder.dropoff_zone(drop_off_zone),
|
drop_off=dz,
|
||||||
target=assault_area,
|
target=assault_area,
|
||||||
nav_to_home=builder.nav_path(
|
nav_to_home=builder.nav_path(
|
||||||
drop_off_zone.position,
|
drop_off_zone.position,
|
||||||
|
|||||||
@ -23,7 +23,7 @@ from game.theater import (
|
|||||||
TheaterGroundObject,
|
TheaterGroundObject,
|
||||||
TheaterUnit,
|
TheaterUnit,
|
||||||
)
|
)
|
||||||
from game.utils import Distance, meters, nautical_miles
|
from game.utils import Distance, meters, nautical_miles, feet
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game.coalition import Coalition
|
from game.coalition import Coalition
|
||||||
@ -225,15 +225,17 @@ class WaypointBuilder:
|
|||||||
position: Point,
|
position: Point,
|
||||||
objective: MissionTarget,
|
objective: MissionTarget,
|
||||||
) -> FlightWaypoint:
|
) -> FlightWaypoint:
|
||||||
|
alt = self.doctrine.ingress_altitude
|
||||||
alt_type: AltitudeReference = "BARO"
|
alt_type: AltitudeReference = "BARO"
|
||||||
if self.is_helo:
|
if self.is_helo or self.flight.is_hercules:
|
||||||
alt_type = "RADIO"
|
alt_type = "RADIO"
|
||||||
|
alt = meters(60) if self.is_helo else feet(1000)
|
||||||
|
|
||||||
return FlightWaypoint(
|
return FlightWaypoint(
|
||||||
"INGRESS",
|
"INGRESS",
|
||||||
ingress_type,
|
ingress_type,
|
||||||
position,
|
position,
|
||||||
meters(60) if self.is_helo else self.doctrine.ingress_altitude,
|
alt,
|
||||||
alt_type,
|
alt_type,
|
||||||
description=f"INGRESS on {objective.name}",
|
description=f"INGRESS on {objective.name}",
|
||||||
pretty_name=f"INGRESS on {objective.name}",
|
pretty_name=f"INGRESS on {objective.name}",
|
||||||
|
|||||||
@ -29,6 +29,7 @@ from dcs.unitgroup import FlyingGroup
|
|||||||
from game.ato import Flight, FlightType
|
from game.ato import Flight, FlightType
|
||||||
from game.ato.flightplans.aewc import AewcFlightPlan
|
from game.ato.flightplans.aewc import AewcFlightPlan
|
||||||
from game.ato.flightplans.theaterrefueling import TheaterRefuelingFlightPlan
|
from game.ato.flightplans.theaterrefueling import TheaterRefuelingFlightPlan
|
||||||
|
from game.dcs.aircrafttype import AircraftType
|
||||||
|
|
||||||
|
|
||||||
class AircraftBehavior:
|
class AircraftBehavior:
|
||||||
@ -298,11 +299,15 @@ class AircraftBehavior:
|
|||||||
|
|
||||||
def configure_transport(self, group: FlyingGroup[Any], flight: Flight) -> None:
|
def configure_transport(self, group: FlyingGroup[Any], flight: Flight) -> None:
|
||||||
group.task = Transport.name
|
group.task = Transport.name
|
||||||
|
roe = OptROE.Values.WeaponHold
|
||||||
|
if flight.is_hercules:
|
||||||
|
group.task = GroundAttack.name
|
||||||
|
roe = OptROE.Values.OpenFire
|
||||||
self.configure_behavior(
|
self.configure_behavior(
|
||||||
flight,
|
flight,
|
||||||
group,
|
group,
|
||||||
react_on_threat=OptReactOnThreat.Values.EvadeFire,
|
react_on_threat=OptReactOnThreat.Values.EvadeFire,
|
||||||
roe=OptROE.Values.WeaponHold,
|
roe=roe,
|
||||||
restrict_jettison=True,
|
restrict_jettison=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
from dcs.point import MovingPoint
|
||||||
|
from dcs.task import Expend, WeaponType, CarpetBombing, OptROE
|
||||||
|
|
||||||
|
from game.ato.flightwaypointtype import FlightWaypointType
|
||||||
|
from game.utils import feet, knots
|
||||||
|
from pydcs_extensions.hercules.hercules import Hercules
|
||||||
|
from .pydcswaypointbuilder import PydcsWaypointBuilder
|
||||||
|
|
||||||
|
|
||||||
|
class AirAssaultIngressBuilder(PydcsWaypointBuilder):
|
||||||
|
def add_tasks(self, waypoint: MovingPoint) -> None:
|
||||||
|
air_drop = self.group.units[0].unit_type in [Hercules]
|
||||||
|
if air_drop:
|
||||||
|
waypoint.speed = knots(230).meters_per_second
|
||||||
|
waypoint.speed_locked = True
|
||||||
|
waypoint.ETA_locked = False
|
||||||
|
tgt = self.flight.flight_plan.package.target.position
|
||||||
|
for wpt in self.flight.flight_plan.waypoints:
|
||||||
|
if wpt.waypoint_type == FlightWaypointType.TARGET_GROUP_LOC:
|
||||||
|
tgt = wpt.position
|
||||||
|
break
|
||||||
|
bombing = CarpetBombing(
|
||||||
|
tgt,
|
||||||
|
weapon_type=WeaponType.Bombs,
|
||||||
|
expend=Expend.All,
|
||||||
|
carpet_length=feet(9000).meters,
|
||||||
|
)
|
||||||
|
waypoint.add_task(bombing)
|
||||||
@ -20,6 +20,7 @@ from game.missiongenerator.aircraft.waypoints.cargostop import CargoStopBuilder
|
|||||||
from game.missiongenerator.missiondata import MissionData
|
from game.missiongenerator.missiondata import MissionData
|
||||||
from game.settings import Settings
|
from game.settings import Settings
|
||||||
from game.utils import pairwise
|
from game.utils import pairwise
|
||||||
|
from .airassaultingress import AirAssaultIngressBuilder
|
||||||
from .baiingress import BaiIngressBuilder
|
from .baiingress import BaiIngressBuilder
|
||||||
from .landingzone import LandingZoneBuilder
|
from .landingzone import LandingZoneBuilder
|
||||||
from .casingress import CasIngressBuilder
|
from .casingress import CasIngressBuilder
|
||||||
@ -136,6 +137,7 @@ class WaypointGenerator:
|
|||||||
FlightWaypointType.DROPOFF_ZONE: LandingZoneBuilder,
|
FlightWaypointType.DROPOFF_ZONE: LandingZoneBuilder,
|
||||||
FlightWaypointType.REFUEL: RefuelPointBuilder,
|
FlightWaypointType.REFUEL: RefuelPointBuilder,
|
||||||
FlightWaypointType.CARGO_STOP: CargoStopBuilder,
|
FlightWaypointType.CARGO_STOP: CargoStopBuilder,
|
||||||
|
FlightWaypointType.INGRESS_AIR_ASSAULT: AirAssaultIngressBuilder,
|
||||||
}
|
}
|
||||||
builder = builders.get(waypoint.waypoint_type, DefaultWaypointBuilder)
|
builder = builders.get(waypoint.waypoint_type, DefaultWaypointBuilder)
|
||||||
return builder(
|
return builder(
|
||||||
|
|||||||
@ -31,7 +31,7 @@ platformdirs==2.5.4
|
|||||||
pluggy==1.0.0
|
pluggy==1.0.0
|
||||||
pre-commit==2.20.0
|
pre-commit==2.20.0
|
||||||
pydantic==1.10.2
|
pydantic==1.10.2
|
||||||
-e git+https://github.com/dcs-retribution/pydcs@f0bb4da4d458d714dedd1f3bba30deae5f25a80d#egg=pydcs
|
-e git+https://github.com/dcs-retribution/pydcs@fb1fefcb32fbab82ac36b8519b87bae32326784e#egg=pydcs
|
||||||
pyinstaller==5.6.2
|
pyinstaller==5.6.2
|
||||||
pyinstaller-hooks-contrib==2022.13
|
pyinstaller-hooks-contrib==2022.13
|
||||||
pyparsing==3.0.9
|
pyparsing==3.0.9
|
||||||
|
|||||||
@ -121,6 +121,52 @@ local unitPayloads = {
|
|||||||
[1] = 31,
|
[1] = 31,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
[9] = {
|
||||||
|
["displayName"] = "Retribution CAS",
|
||||||
|
["name"] = "Retribution CAS",
|
||||||
|
["pylons"] = {
|
||||||
|
[1] = {
|
||||||
|
["CLSID"] = "Herc_JATO",
|
||||||
|
["num"] = 1,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
["CLSID"] = "{Herc_105mm_Howitzer}",
|
||||||
|
["num"] = 8,
|
||||||
|
},
|
||||||
|
[3] = {
|
||||||
|
["CLSID"] = "{Herc_M61_Vulcan_Rotary_Cannon}",
|
||||||
|
["num"] = 6,
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
["CLSID"] = "{Herc_GAU_23A_Chain_Gun}",
|
||||||
|
["num"] = 7,
|
||||||
|
},
|
||||||
|
[5] = {
|
||||||
|
["CLSID"] = "Herc_BattleStation_TGP",
|
||||||
|
["num"] = 9,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["tasks"] = {
|
||||||
|
[1] = 35,
|
||||||
|
[2] = 31,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[10] = {
|
||||||
|
["name"] = "Retribution Air Assault",
|
||||||
|
["pylons"] = {
|
||||||
|
[1] = {
|
||||||
|
["CLSID"] = "Herc_Soldier_Squad",
|
||||||
|
["num"] = 12,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
["CLSID"] = "Herc_JATO",
|
||||||
|
["num"] = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
["tasks"] = {
|
||||||
|
[1] = 32,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
["tasks"] = {
|
["tasks"] = {
|
||||||
},
|
},
|
||||||
|
|||||||
@ -490,11 +490,11 @@ function Hercules_Cargo.Cargo_Initialize(initiator, Cargo_Contents, Cargo_Type_n
|
|||||||
Herc_Cargo[Herc_j].all_cargo_survive_to_the_ground = true
|
Herc_Cargo[Herc_j].all_cargo_survive_to_the_ground = true
|
||||||
else
|
else
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
if Hercules_Cargo.Calculate_Object_Height_AGL(Cargo_Drop_initiator) < 100.0 then--aircraft more than 10m but less than 100m above ground
|
if Hercules_Cargo.Calculate_Object_Height_AGL(Cargo_Drop_initiator) < 152.4 then--aircraft more than 30ft but less than 500ft above ground
|
||||||
Herc_Cargo[Herc_j].all_cargo_gets_destroyed = true
|
Herc_Cargo[Herc_j].all_cargo_gets_destroyed = true
|
||||||
else
|
else
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
Herc_Cargo[Herc_j].destroy_cargo_dropped_without_parachute = true--aircraft more than 100m above ground
|
Herc_Cargo[Herc_j].destroy_cargo_dropped_without_parachute = true--aircraft more than 152.4m (500ft)above ground
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -568,7 +568,7 @@ function Hercules_Cargo.Hercules_Cargo_Drop_Events:onEvent(Cargo_Drop_Event)
|
|||||||
local Cargo_Container_Enclosed = Hercules_Cargo.types[GT_DisplayName]['container']
|
local Cargo_Container_Enclosed = Hercules_Cargo.types[GT_DisplayName]['container']
|
||||||
Hercules_Cargo.Cargo_Initialize(Cargo_Drop_Event.initiator, Cargo_Drop_Event.weapon, GT_Name, Cargo_Container_Enclosed)
|
Hercules_Cargo.Cargo_Initialize(Cargo_Drop_Event.initiator, Cargo_Drop_Event.weapon, GT_Name, Cargo_Container_Enclosed)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
world.addEventHandler(Hercules_Cargo.Hercules_Cargo_Drop_Events)
|
world.addEventHandler(Hercules_Cargo.Hercules_Cargo_Drop_Events)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user