Air Assault for C-130 mod

Resolves #49
This commit is contained in:
Raffson 2022-12-27 19:48:09 +01:00
parent d26fc84316
commit c37c56c879
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
9 changed files with 114 additions and 16 deletions

View File

@ -7,6 +7,7 @@ from typing import Any, List, Optional, TYPE_CHECKING
from dcs import Point
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 .flightstate import FlightState, Navigating, Uninitialized
from .flightstate.killed import Killed
@ -18,9 +19,9 @@ from ..sidc import (
Status,
SymbolSet,
)
from game.dcs.aircrafttype import AircraftType
if TYPE_CHECKING:
from game.dcs.aircrafttype import AircraftType
from game.sim.gameupdateevents import GameUpdateEvents
from game.sim.simulationresults import SimulationResults
from game.squadrons import Squadron, Pilot
@ -161,6 +162,10 @@ class Flight(SidcDescribable):
def is_helo(self) -> bool:
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
def from_cp(self) -> ControlPoint:
return self.departure
@ -197,6 +202,8 @@ class Flight(SidcDescribable):
return Su_33.fuel_max * 0.8
elif unit_type in {C_101EB, C_101CC}:
return unit_type.fuel_max * 0.5
elif unit_type == Hercules:
return unit_type.fuel_max * 0.75
return None
def __repr__(self) -> str:

View File

@ -25,7 +25,7 @@ class AirAssaultLayout(StandardLayout):
pickup: FlightWaypoint | None
nav_to_ingress: list[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
# waypoint. It is used by CTLD as the destination for unloaded troops.
target: FlightWaypoint
@ -37,7 +37,8 @@ class AirAssaultLayout(StandardLayout):
yield self.pickup
yield from self.nav_to_ingress
yield self.ingress
yield self.drop_off
if self.drop_off is not None:
yield self.drop_off
yield self.target
yield from self.nav_to_home
yield self.arrival
@ -53,7 +54,9 @@ class AirAssaultFlightPlan(StandardFlightPlan[AirAssaultLayout], UiZoneDisplay):
@property
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:
if waypoint == self.tot_waypoint:
@ -80,8 +83,10 @@ class AirAssaultFlightPlan(StandardFlightPlan[AirAssaultLayout], UiZoneDisplay):
class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
def layout(self) -> AirAssaultLayout:
if not self.flight.is_helo:
raise PlanningError("Air assault is only usable by helicopters")
if not self.flight.is_helo and not self.flight.is_hercules:
raise PlanningError(
"Air assault is only usable by helicopters and Anubis' C-130 mod"
)
assert self.package.waypoints is not None
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)
if self.flight.departure.cptype in [
if self.flight.is_hercules or self.flight.departure.cptype in [
ControlPointType.AIRCRAFT_CARRIER_GROUP,
ControlPointType.LHA_GROUP,
ControlPointType.OFF_MAP,
@ -114,12 +119,15 @@ class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
pickup_position = pickup.position
assault_area = builder.assault_area(self.package.target)
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.
drop_off_zone = MissionTarget(
"Dropoff zone",
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(
departure=builder.takeoff(self.flight.departure),
@ -135,7 +143,7 @@ class Builder(IBuilder[AirAssaultFlightPlan, AirAssaultLayout]):
self.package.waypoints.ingress,
self.package.target,
),
drop_off=builder.dropoff_zone(drop_off_zone),
drop_off=dz,
target=assault_area,
nav_to_home=builder.nav_path(
drop_off_zone.position,

View File

@ -23,7 +23,7 @@ from game.theater import (
TheaterGroundObject,
TheaterUnit,
)
from game.utils import Distance, meters, nautical_miles
from game.utils import Distance, meters, nautical_miles, feet
if TYPE_CHECKING:
from game.coalition import Coalition
@ -225,15 +225,17 @@ class WaypointBuilder:
position: Point,
objective: MissionTarget,
) -> FlightWaypoint:
alt = self.doctrine.ingress_altitude
alt_type: AltitudeReference = "BARO"
if self.is_helo:
if self.is_helo or self.flight.is_hercules:
alt_type = "RADIO"
alt = meters(60) if self.is_helo else feet(1000)
return FlightWaypoint(
"INGRESS",
ingress_type,
position,
meters(60) if self.is_helo else self.doctrine.ingress_altitude,
alt,
alt_type,
description=f"INGRESS on {objective.name}",
pretty_name=f"INGRESS on {objective.name}",

View File

@ -29,6 +29,7 @@ from dcs.unitgroup import FlyingGroup
from game.ato import Flight, FlightType
from game.ato.flightplans.aewc import AewcFlightPlan
from game.ato.flightplans.theaterrefueling import TheaterRefuelingFlightPlan
from game.dcs.aircrafttype import AircraftType
class AircraftBehavior:
@ -298,11 +299,15 @@ class AircraftBehavior:
def configure_transport(self, group: FlyingGroup[Any], flight: Flight) -> None:
group.task = Transport.name
roe = OptROE.Values.WeaponHold
if flight.is_hercules:
group.task = GroundAttack.name
roe = OptROE.Values.OpenFire
self.configure_behavior(
flight,
group,
react_on_threat=OptReactOnThreat.Values.EvadeFire,
roe=OptROE.Values.WeaponHold,
roe=roe,
restrict_jettison=True,
)

View File

@ -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)

View File

@ -20,6 +20,7 @@ from game.missiongenerator.aircraft.waypoints.cargostop import CargoStopBuilder
from game.missiongenerator.missiondata import MissionData
from game.settings import Settings
from game.utils import pairwise
from .airassaultingress import AirAssaultIngressBuilder
from .baiingress import BaiIngressBuilder
from .landingzone import LandingZoneBuilder
from .casingress import CasIngressBuilder
@ -136,6 +137,7 @@ class WaypointGenerator:
FlightWaypointType.DROPOFF_ZONE: LandingZoneBuilder,
FlightWaypointType.REFUEL: RefuelPointBuilder,
FlightWaypointType.CARGO_STOP: CargoStopBuilder,
FlightWaypointType.INGRESS_AIR_ASSAULT: AirAssaultIngressBuilder,
}
builder = builders.get(waypoint.waypoint_type, DefaultWaypointBuilder)
return builder(

View File

@ -31,7 +31,7 @@ platformdirs==2.5.4
pluggy==1.0.0
pre-commit==2.20.0
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-hooks-contrib==2022.13
pyparsing==3.0.9

View File

@ -121,6 +121,52 @@ local unitPayloads = {
[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"] = {
},

View File

@ -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
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
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
@ -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']
Hercules_Cargo.Cargo_Initialize(Cargo_Drop_Event.initiator, Cargo_Drop_Event.weapon, GT_Name, Cargo_Container_Enclosed)
end
end
end
end
world.addEventHandler(Hercules_Cargo.Hercules_Cargo_Drop_Events)