EW Script 2.0 - Enable for AI (#491)

* EW Script 2.0 - Enable for AI

* Refactor

* Remove unnecessary code + refactor

* Fix test -_-

* Cleanup

---------

Co-authored-by: Raffson <Raffson@users.noreply.github.com>
Co-authored-by: Starfire13 <72491792+Starfire13@users.noreply.github.com>
This commit is contained in:
Drexyl 2025-03-24 06:32:51 +11:00 committed by GitHub
parent c3fea788f3
commit af4bba7396
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 152 additions and 33 deletions

View File

@ -173,18 +173,24 @@ class FlightGroupConfigurator:
self, unit: FlyingUnit, member: FlightMember, laser_codes: list[Optional[int]]
) -> None:
self.set_skill(unit, member)
if (code := member.tgp_laser_code) is not None:
laser_codes.append(code.code)
else:
laser_codes.append(None)
settings = self.flight.coalition.game.settings
if not member.is_player or not settings.plugins.get("ewrj"):
self.handle_ew_jamming(member, unit)
def handle_ew_jamming(self, member: FlightMember, unit: FlyingUnit) -> None:
if not member.is_player:
return
settings = self.flight.coalition.game.settings
# Check if ecm_required option is enabled
jammer_required = settings.plugin_option("ewrj.ecm_required")
if jammer_required:
ecm = WeaponType.JAMMER
if not member.loadout.has_weapon_of_type(ecm):
return
has_jammer = member.loadout.has_weapon_of_type(WeaponType.JAMMER)
if jammer_required and not has_jammer:
return
# Create the original ewrj_menu_trigger for player flight members
ewrj_menu_trigger = TriggerStart(comment=f"EWRJ-{unit.name}")
ewrj_menu_trigger.add_action(DoScript(String(f'EWJamming("{unit.name}")')))
self.mission.triggerrules.triggers.append(ewrj_menu_trigger)

View File

@ -9,9 +9,13 @@ from dcs.task import (
OptFormation,
Targets,
SetUnlimitedFuelCommand,
RunScript,
OptReactOnThreat,
)
from game.ato import FlightType
from game.data.doctrine import Doctrine
from game.data.weapons import WeaponType
from game.theater import NavalControlPoint
from game.utils import nautical_miles, feet
from .pydcswaypointbuilder import PydcsWaypointBuilder
@ -54,29 +58,24 @@ class JoinPointBuilder(PydcsWaypointBuilder):
max_dist=doctrine.escort_engagement_range.nautical_miles,
vertical_spacing=doctrine.escort_spacing.feet,
)
elif self.flight.flight_type == FlightType.SEAD_ESCORT:
if isinstance(self.flight.package.target, NavalControlPoint):
self.configure_escort_tasks(
waypoint,
[
Targets.All.Naval.id,
Targets.All.GroundUnits.AirDefence.AAA.SAMRelated.id,
],
max_dist=doctrine.sead_escort_engagement_range.nautical_miles,
vertical_spacing=doctrine.sead_escort_spacing.feet,
elif self.flight.flight_type in [
FlightType.SEAD_SWEEP,
FlightType.SEAD,
FlightType.SEAD_ESCORT,
]:
self.start_defensive_jamming(waypoint)
if self.flight.flight_type == FlightType.SEAD_ESCORT:
self.handle_sead_escort(doctrine, waypoint)
# Let the AI use ECM to preemptively defend themselves.
ecm_option = OptECMUsing(
value=OptECMUsing.Values.UseIfDetectedLockByRadar
)
waypoint.tasks.append(ecm_option)
else:
self.configure_escort_tasks(
waypoint,
[Targets.All.GroundUnits.AirDefence.AAA.SAMRelated.id],
max_dist=doctrine.sead_escort_engagement_range.nautical_miles,
vertical_spacing=doctrine.sead_escort_spacing.feet,
)
# Let the AI use ECM to preemptively defend themselves.
ecm_option = OptECMUsing(value=OptECMUsing.Values.UseIfDetectedLockByRadar)
waypoint.tasks.append(ecm_option)
# Let the AI use ECM to defend themselves.
ecm_option = OptECMUsing(value=OptECMUsing.Values.UseIfOnlyLockByRadar)
waypoint.tasks.append(ecm_option)
elif not self.flight.flight_type.is_air_to_air:
# Capture any non A/A type to avoid issues with SPJs that use the primary radar such as the F/A-18C.
# You can bully them with STT to not be able to fire radar guided missiles at you,
@ -86,6 +85,47 @@ class JoinPointBuilder(PydcsWaypointBuilder):
ecm_option = OptECMUsing(value=OptECMUsing.Values.UseIfOnlyLockByRadar)
waypoint.tasks.append(ecm_option)
def handle_sead_escort(self, doctrine: Doctrine, waypoint: MovingPoint) -> None:
if isinstance(self.flight.package.target, NavalControlPoint):
self.configure_escort_tasks(
waypoint,
[
Targets.All.Naval.id,
Targets.All.GroundUnits.AirDefence.AAA.SAMRelated.id,
],
max_dist=doctrine.sead_escort_engagement_range.nautical_miles,
vertical_spacing=doctrine.sead_escort_spacing.feet,
)
else:
self.configure_escort_tasks(
waypoint,
[Targets.All.GroundUnits.AirDefence.AAA.SAMRelated.id],
max_dist=doctrine.sead_escort_engagement_range.nautical_miles,
vertical_spacing=doctrine.sead_escort_spacing.feet,
)
def start_defensive_jamming(self, waypoint: MovingPoint) -> None:
# Start Defensive Jamming
settings = self.flight.coalition.game.settings
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
if settings.plugins.get("ewrj") and ai_jammer:
ecm_required = settings.plugin_option("ewrj.ecm_required")
has_jammer = False
for unit, member in zip(self.group.units, self.flight.iter_members()):
has_jammer = member.loadout.has_weapon_of_type(WeaponType.JAMMER)
if ecm_required and not has_jammer:
continue
if not member.is_player:
script_content = f'startDjamming("{unit.name}")'
start_jamming_script = RunScript(script_content)
waypoint.tasks.append(start_jamming_script)
has_jammer = True
if has_jammer:
passive_defense = OptReactOnThreat(
OptReactOnThreat.Values.PassiveDefense
)
waypoint.tasks.append(passive_defense)
def configure_escort_tasks(
self,
waypoint: MovingPoint,

View File

@ -9,6 +9,8 @@ from dcs.task import (
Tanker,
Targets,
SetUnlimitedFuelCommand,
RunScript,
OptReactOnThreat,
)
from game.ato import FlightType
@ -38,6 +40,22 @@ class RaceTrackBuilder(PydcsWaypointBuilder):
)
return
if self.flight.flight_type == FlightType.AEWC:
# Start Offensive Jamming for all AWACS flights
settings = self.flight.coalition.game.settings
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
if settings.plugins.get("ewrj") and ai_jammer:
# all units in group are AWACS, no specific checks needed
for unit, member in zip(self.group.units, self.flight.iter_members()):
script_content = f'startEWjamm("{unit.name}")'
start_jamming_script = RunScript(script_content)
waypoint.tasks.append(start_jamming_script)
passive_defense = OptReactOnThreat(
OptReactOnThreat.Values.PassiveDefense
)
waypoint.tasks.append(passive_defense)
# NB: It's important that the engage task comes before the orbit task.
# Though they're on the same waypoint, if the orbit task comes first it
# is their first priority and they will not engage any targets because

View File

@ -1,8 +1,13 @@
import logging
from dcs.point import MovingPoint
from dcs.task import SetUnlimitedFuelCommand
from dcs.task import (
SetUnlimitedFuelCommand,
RunScript,
OptReactOnThreat,
)
from game.ato import FlightType
from game.ato.flightplans.patrolling import PatrollingFlightPlan
from .pydcswaypointbuilder import PydcsWaypointBuilder
@ -13,6 +18,21 @@ class RaceTrackEndBuilder(PydcsWaypointBuilder):
if self.flight.squadron.coalition.game.settings.ai_unlimited_fuel:
waypoint.tasks.insert(0, SetUnlimitedFuelCommand(True))
# Disable Offensive Jamming at Racetrack End
if self.flight.flight_type == FlightType.AEWC:
# Stop Offensive Jamming for all AWACS flights
settings = self.flight.coalition.game.settings
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
if settings.plugins.get("ewrj") and ai_jammer:
# all units in group are AWACS, no specific checks needed
for unit, member in zip(self.group.units, self.flight.iter_members()):
script_content = f'stopEWjamming("{unit.name}")'
stop_jamming_script = RunScript(script_content)
waypoint.tasks.append(stop_jamming_script)
evade_fire = OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)
waypoint.tasks.append(evade_fire)
def build(self) -> MovingPoint:
waypoint = super().build()

View File

@ -2,11 +2,14 @@ from dcs.point import MovingPoint
from dcs.task import (
OptECMUsing,
OptFormation,
RunScript,
SetUnlimitedFuelCommand,
SwitchWaypoint,
RunScript,
OptReactOnThreat,
)
from game.ato import FlightType
from game.data.weapons import WeaponType
from game.utils import knots
from .pydcswaypointbuilder import PydcsWaypointBuilder
@ -41,6 +44,33 @@ class SplitPointBuilder(PydcsWaypointBuilder):
f'trigger.action.setUserFlag("split-{id(self.package)}", true)'
)
waypoint.tasks.append(script)
elif self.flight.flight_type.is_escort_type:
index = len(self.group.points)
self.group.add_trigger_action(SwitchWaypoint(None, index))
elif self.flight.flight_type in [
FlightType.SEAD_SWEEP,
FlightType.SEAD,
FlightType.SEAD_ESCORT,
]:
if self.flight.flight_type == FlightType.SEAD_ESCORT:
# Moved previous escort split tasks
if self.flight.flight_type.is_escort_type:
index = len(self.group.points)
self.group.add_trigger_action(SwitchWaypoint(None, index))
self.stop_defensive_jamming(waypoint)
def stop_defensive_jamming(self, waypoint: MovingPoint) -> None:
# Stop Defensive Jamming
settings = self.flight.coalition.game.settings
ai_jammer = settings.plugin_option("ewrj.ai_jammer_enabled")
if settings.plugins.get("ewrj") and ai_jammer:
for unit, member in zip(self.group.units, self.flight.iter_members()):
if settings.plugin_option("ewrj.ecm_required"):
ecm = WeaponType.JAMMER
if not member.loadout.has_weapon_of_type(ecm):
continue
if not member.is_player:
script_content = f'stopDjamming("{unit.name}")'
stop_jamming_script = RunScript(script_content)
waypoint.tasks.append(stop_jamming_script)
evaide_fire = OptReactOnThreat(OptReactOnThreat.Values.EvadeFire)
waypoint.tasks.append(evaide_fire)

View File

@ -1,11 +1,16 @@
{
"nameInUI": "EW Jammer (for player only)",
"nameInUI": "EW Jammer Scipt 2.0",
"defaultValue": false,
"specificOptions": [
{
"nameInUI": "Require ECM pod",
"mnemonic": "ecm_required",
"defaultValue": true
},
{
"nameInUI": "Enable AI Jammers",
"mnemonic": "ai_jammer_enabled",
"defaultValue": false
}
],
"scriptsWorkOrders": [