mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Settings doctrine page + streamlining (#156)
* Added a separate Doctrine page in settings with the following new options: - Minimum number of aircraft for autoplanner to plan OCA packages against - Airbase threat range (nmi) - TARCAP threat buffer distance (nmi) - AEW&C threat buffer distance (nmi) - Theater tanker threat buffer distance (nmi) Implemented handling for the OPFOR autoplanner aggressiveness in objectivefinder.py vulnerable_control_points(). * * Added three new options in Settings: - Autoplanner plans refueling flights for Strike packages - Autoplanner plans refueling flights for OCA packages - Autoplanner plans refueling flights for DEAD packages Fixed a bug in faction.py where F-16Ds were not correctly removed from the faction when the F-16I/F-16D mod was not selected. * Renamed Maximum frontline length -> Maximum frontline width.
This commit is contained in:
parent
4b4ec8d9ad
commit
6e37cadb84
14
changelog.md
14
changelog.md
@ -7,6 +7,17 @@
|
||||
* **[Campaign Design]** Ability to define SCENERY REMOVE OBJECTS ZONE triggers with the roadbase objects in campaign miz. This might not work reliably in multiplayer due to DCS issues. FARPs can be used to remove scenery objects in multiplayer.
|
||||
* **[Campaign Management]** Improved squadron retreat logic at longer ranges.
|
||||
* **[Options]** Ability to load & save your settings.
|
||||
* **[Options]** Added a separate Doctrine page in settings with the following new options:
|
||||
* Minimum number of aircraft for autoplanner to plan OCA packages against
|
||||
* Airbase threat range (nmi)
|
||||
* TARCAP threat buffer distance (nmi)
|
||||
* AEW&C threat buffer distance (nmi)
|
||||
* Theater tanker threat buffer distance (nmi)
|
||||
* **[Options]** Improved the option to configure OPFOR autoplanner aggressiveness. The AI might now take even more risks and plan missions against defended targets.
|
||||
* Added three new options in Settings:
|
||||
* Autoplanner plans refueling flights for Strike packages
|
||||
* Autoplanner plans refueling flights for OCA packages
|
||||
* Autoplanner plans refueling flights for DEAD packages
|
||||
* **[UI]** Added fuel selector in flight's edit window.
|
||||
* **[Plugins]** Expose Splash Damage's "game_messages" option and set its default to false.
|
||||
* **[Mission Generation]** Improved AI SEAD capabilities, allowing for mixed loadouts using Decoys, ARMs & ASMs.
|
||||
@ -33,13 +44,14 @@
|
||||
* **[Plugins]** Added "EWR Jammer" plugin (only for humans, may change in the future).
|
||||
* **[Campaign]** New campaign (Operation Desert Sabre) by Chimiste
|
||||
* **[Plugins]** Updated CTLD to latest released version
|
||||
* **[Options]** Renamed Maximum frontline length -> Maximum frontline width.
|
||||
|
||||
## Fixes
|
||||
* **[New Game Wizard]** Settings would not persist when going back to a previous page (obsolete due to overhaul).
|
||||
* **[Mission Generation]** Unused aircraft are no longer claimed, fixing a bug where these aircraft would no longer be available after aborting the mission.
|
||||
* **[Mission Generation]** Fixed (potential) bug in helipad assignments at FOBs/FARPs.
|
||||
* **[Mission Generation]** Fix AI immediately returning to base when forced to air-start due to insufficient parking space.
|
||||
|
||||
* **[Modding]** Fixed a bug where F-16Ds were not correctly removed from the faction when the F-16I/F-16D mod was not selected
|
||||
|
||||
# Retribution v1.1.1 (hotfix)
|
||||
|
||||
|
||||
@ -48,7 +48,9 @@ class Builder(IBuilder[AewcFlightPlan, PatrollingLayout]):
|
||||
orbit_heading = heading_to_threat_boundary
|
||||
|
||||
# Station 80nm outside the threat zone.
|
||||
threat_buffer = nautical_miles(80)
|
||||
threat_buffer = nautical_miles(
|
||||
self.flight.coalition.game.settings.aewc_threat_buffer_min_distance
|
||||
)
|
||||
if self.threat_zones.threatened(location.position):
|
||||
orbit_distance = distance_to_threat + threat_buffer
|
||||
else:
|
||||
|
||||
@ -60,7 +60,9 @@ class CapBuilder(IBuilder[FlightPlanT, LayoutT], ABC):
|
||||
# distance from the nearest enemy airbase, but since they are by
|
||||
# definition in enemy territory they can't avoid the threat zone
|
||||
# without being useless.
|
||||
min_distance_from_enemy = nautical_miles(20)
|
||||
min_distance_from_enemy = nautical_miles(
|
||||
self.coalition.game.settings.tarcap_threat_buffer_min_distance
|
||||
)
|
||||
distance_to_airfield = meters(
|
||||
closest_airfield.position.distance_to_point(
|
||||
self.package.target.position
|
||||
|
||||
@ -53,7 +53,7 @@ class CasFlightPlan(PatrollingFlightPlan[CasLayout], UiZoneDisplay):
|
||||
|
||||
@property
|
||||
def engagement_distance(self) -> Distance:
|
||||
max_length = self.flight.coalition.game.settings.max_frontline_length * 1000
|
||||
max_length = self.flight.coalition.game.settings.max_frontline_width * 1000
|
||||
return meters(max_length) / 2
|
||||
|
||||
@property
|
||||
|
||||
@ -36,7 +36,9 @@ class Builder(IBuilder[TheaterRefuelingFlightPlan, PatrollingLayout]):
|
||||
orbit_heading = heading_to_threat_boundary
|
||||
|
||||
# Station 70nm outside the threat zone.
|
||||
threat_buffer = nautical_miles(70)
|
||||
threat_buffer = nautical_miles(
|
||||
self.flight.coalition.game.settings.tanker_threat_buffer_min_distance
|
||||
)
|
||||
if self.threat_zones.threatened(location.position):
|
||||
orbit_distance = distance_to_threat + threat_buffer
|
||||
else:
|
||||
|
||||
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
import math
|
||||
import operator
|
||||
from collections.abc import Iterable, Iterator
|
||||
from random import randint
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
|
||||
from game.ato.closestairfields import ClosestAirfields, ObjectiveDistanceCache
|
||||
@ -33,10 +34,6 @@ MissionTargetType = TypeVar("MissionTargetType", bound=MissionTarget)
|
||||
class ObjectiveFinder:
|
||||
"""Identifies potential objectives for the mission planner."""
|
||||
|
||||
# TODO: Merge into doctrine.
|
||||
AIRFIELD_THREAT_RANGE = nautical_miles(150)
|
||||
SAM_THREAT_RANGE = nautical_miles(100)
|
||||
|
||||
def __init__(self, game: Game, is_player: bool) -> None:
|
||||
self.game = game
|
||||
self.is_player = is_player
|
||||
@ -151,9 +148,18 @@ class ObjectiveFinder:
|
||||
# Off-map spawn locations don't need protection.
|
||||
continue
|
||||
airfields_in_proximity = self.closest_airfields_to(cp)
|
||||
airbase_threat_range = self.game.settings.airbase_threat_range
|
||||
if (
|
||||
not self.is_player
|
||||
and randint(1, 100)
|
||||
> self.game.settings.opfor_autoplanner_aggressiveness
|
||||
):
|
||||
# Chance that the airfield threat range will be evaluated as zero,
|
||||
# causing the OPFOR autoplanner to plan offensively
|
||||
airbase_threat_range = 0
|
||||
airfields_in_threat_range = (
|
||||
airfields_in_proximity.operational_airfields_within(
|
||||
self.AIRFIELD_THREAT_RANGE
|
||||
nautical_miles(airbase_threat_range)
|
||||
)
|
||||
)
|
||||
for airfield in airfields_in_threat_range:
|
||||
|
||||
@ -44,3 +44,5 @@ class PlanDead(PackagePlanningTask[IadsGroundObject]):
|
||||
self.propose_flight(FlightType.SEAD, 2)
|
||||
self.propose_flight(FlightType.SEAD_ESCORT, 2, EscortType.Sead)
|
||||
self.propose_flight(FlightType.ESCORT, 2, EscortType.AirToAir)
|
||||
if self.target.control_point.coalition.game.settings.autoplan_tankers_for_dead:
|
||||
self.propose_flight(FlightType.REFUELING, 1)
|
||||
|
||||
@ -29,3 +29,5 @@ class PlanOcaStrike(PackagePlanningTask[ControlPoint]):
|
||||
if self.aircraft_cold_start:
|
||||
self.propose_flight(FlightType.OCA_AIRCRAFT, 2)
|
||||
self.propose_common_escorts()
|
||||
if self.target.coalition.game.settings.autoplan_tankers_for_oca:
|
||||
self.propose_flight(FlightType.REFUELING, 1)
|
||||
|
||||
@ -24,3 +24,5 @@ class PlanStrike(PackagePlanningTask[TheaterGroundObject]):
|
||||
tgt_count = self.target.alive_unit_count
|
||||
self.propose_flight(FlightType.STRIKE, min(4, (tgt_count // 2) + 1))
|
||||
self.propose_common_escorts()
|
||||
if self.target.coalition.game.settings.autoplan_tankers_for_strike:
|
||||
self.propose_flight(FlightType.REFUELING, 1)
|
||||
|
||||
@ -173,7 +173,11 @@ class TheaterState(WorldState["TheaterState"]):
|
||||
cp: BattlePositions.for_control_point(cp)
|
||||
for cp in ordered_capturable_points
|
||||
},
|
||||
oca_targets=list(finder.oca_targets(min_aircraft=20)),
|
||||
oca_targets=list(
|
||||
finder.oca_targets(
|
||||
min_aircraft=game.settings.oca_target_autoplanner_min_aircraft_count
|
||||
)
|
||||
),
|
||||
strike_targets=list(finder.strike_targets()),
|
||||
enemy_barcaps=list(game.theater.control_points_for(not player)),
|
||||
threat_zones=game.threat_zone_for(not player),
|
||||
|
||||
@ -330,10 +330,10 @@ class Faction:
|
||||
self.remove_aircraft("F-15D")
|
||||
if not mod_settings.f_16_idf:
|
||||
self.remove_aircraft("F-16I")
|
||||
self.remove_aircraft("F_16D_52")
|
||||
self.remove_aircraft("F_16D_50")
|
||||
self.remove_aircraft("F_16D_50_NS")
|
||||
self.remove_aircraft("F_16D_52_NS")
|
||||
self.remove_aircraft("F-16D_52")
|
||||
self.remove_aircraft("F-16D_50")
|
||||
self.remove_aircraft("F-16D_50_NS")
|
||||
self.remove_aircraft("F-16D_52_NS")
|
||||
self.remove_aircraft("F-16D_Barak_30")
|
||||
self.remove_aircraft("F-16D_Barak_40")
|
||||
else:
|
||||
|
||||
@ -64,7 +64,7 @@ class FrontLineConflictDescription:
|
||||
attack_heading = frontline.blue_forward_heading
|
||||
position = cls.find_ground_position(
|
||||
frontline.position,
|
||||
settings.max_frontline_length * 1000,
|
||||
settings.max_frontline_width * 1000,
|
||||
attack_heading.right,
|
||||
theater,
|
||||
)
|
||||
@ -82,13 +82,13 @@ class FrontLineConflictDescription:
|
||||
right_heading = heading.right
|
||||
left_position = cls.extend_ground_position(
|
||||
center_position,
|
||||
int(settings.max_frontline_length * 1000 / 2),
|
||||
int(settings.max_frontline_width * 1000 / 2),
|
||||
left_heading,
|
||||
theater,
|
||||
)
|
||||
right_position = cls.extend_ground_position(
|
||||
center_position,
|
||||
int(settings.max_frontline_length * 1000 / 2),
|
||||
int(settings.max_frontline_width * 1000 / 2),
|
||||
right_heading,
|
||||
theater,
|
||||
)
|
||||
|
||||
@ -46,6 +46,9 @@ PILOTS_AND_SQUADRONS_SECTION = "Pilots and Squadrons"
|
||||
HQ_AUTOMATION_SECTION = "HQ Automation"
|
||||
FLIGHT_PLANNER_AUTOMATION = "Flight Planner Automation"
|
||||
|
||||
CAMPAIGN_DOCTRINE_PAGE = "Campaign Doctrine"
|
||||
DOCTRINE_DISTANCES_SECTION = "Doctrine distances"
|
||||
|
||||
MISSION_GENERATOR_PAGE = "Mission Generator"
|
||||
|
||||
GAMEPLAY_SECTION = "Gameplay"
|
||||
@ -194,6 +197,109 @@ class Settings:
|
||||
"assigned to their primary task."
|
||||
),
|
||||
)
|
||||
autoplan_tankers_for_strike: bool = boolean_option(
|
||||
"Autoplanner plans refueling flights for Strike packages",
|
||||
page=CAMPAIGN_DOCTRINE_PAGE,
|
||||
section=GENERAL_SECTION,
|
||||
default=True,
|
||||
invert=False,
|
||||
detail=(
|
||||
"If checked, the autoplanner will include tankers in Strike packages, "
|
||||
"provided the faction has access to them."
|
||||
),
|
||||
)
|
||||
autoplan_tankers_for_oca: bool = boolean_option(
|
||||
"Autoplanner plans refueling flights for OCA packages",
|
||||
page=CAMPAIGN_DOCTRINE_PAGE,
|
||||
section=GENERAL_SECTION,
|
||||
default=True,
|
||||
invert=False,
|
||||
detail=(
|
||||
"If checked, the autoplanner will include tankers in OCA packages, "
|
||||
"provided the faction has access to them."
|
||||
),
|
||||
)
|
||||
autoplan_tankers_for_dead: bool = boolean_option(
|
||||
"Autoplanner plans refueling flights for DEAD packages",
|
||||
page=CAMPAIGN_DOCTRINE_PAGE,
|
||||
section=GENERAL_SECTION,
|
||||
default=True,
|
||||
invert=False,
|
||||
detail=(
|
||||
"If checked, the autoplanner will include tankers in DEAD packages, "
|
||||
"provided the faction has access to them."
|
||||
),
|
||||
)
|
||||
oca_target_autoplanner_min_aircraft_count: int = bounded_int_option(
|
||||
"Minimum number of aircraft (at vulnerable airfields) for autoplanner to plan OCA packages against",
|
||||
page=CAMPAIGN_DOCTRINE_PAGE,
|
||||
section=GENERAL_SECTION,
|
||||
default=20,
|
||||
min=0,
|
||||
max=100,
|
||||
detail=(
|
||||
"How many aircraft there has to be at an airfield for "
|
||||
"the autoplanner to plan an OCA strike against it."
|
||||
),
|
||||
)
|
||||
opfor_autoplanner_aggressiveness: int = bounded_int_option(
|
||||
"OPFOR autoplanner aggressiveness (%)",
|
||||
page=CAMPAIGN_DOCTRINE_PAGE,
|
||||
section=GENERAL_SECTION,
|
||||
default=20,
|
||||
min=0,
|
||||
max=100,
|
||||
detail=(
|
||||
"Chance (larger number -> higher chance) that the OPFOR AI "
|
||||
"autoplanner will take risks and plan flights against targets "
|
||||
"within threatened airspace."
|
||||
),
|
||||
)
|
||||
airbase_threat_range: int = bounded_int_option(
|
||||
"Airbase threat range (nmi)",
|
||||
page=CAMPAIGN_DOCTRINE_PAGE,
|
||||
section=DOCTRINE_DISTANCES_SECTION,
|
||||
default=100,
|
||||
min=0,
|
||||
max=300,
|
||||
detail=(
|
||||
"Will impact both defensive (BARCAP) and offensive flights. Also has a performance impact,"
|
||||
"lower threat range generally means less BARCAPs are planned."
|
||||
),
|
||||
)
|
||||
tarcap_threat_buffer_min_distance: int = bounded_int_option(
|
||||
"TARCAP threat buffer distance (nmi)",
|
||||
page=CAMPAIGN_DOCTRINE_PAGE,
|
||||
section=DOCTRINE_DISTANCES_SECTION,
|
||||
default=20,
|
||||
min=0,
|
||||
max=100,
|
||||
detail=("How close to known threats will the TARCAP racetrack extend."),
|
||||
)
|
||||
aewc_threat_buffer_min_distance: int = bounded_int_option(
|
||||
"AEW&C threat buffer distance (nmi)",
|
||||
page=CAMPAIGN_DOCTRINE_PAGE,
|
||||
section=DOCTRINE_DISTANCES_SECTION,
|
||||
default=80,
|
||||
min=0,
|
||||
max=300,
|
||||
detail=(
|
||||
"How far, at minimum, will AEW&C racetracks be planned"
|
||||
"to known threat zones."
|
||||
),
|
||||
)
|
||||
tanker_threat_buffer_min_distance: int = bounded_int_option(
|
||||
"Theater tanker threat buffer distance (nmi)",
|
||||
page=CAMPAIGN_DOCTRINE_PAGE,
|
||||
section=DOCTRINE_DISTANCES_SECTION,
|
||||
default=70,
|
||||
min=0,
|
||||
max=300,
|
||||
detail=(
|
||||
"How far, at minimum, will theater tanker racetracks be "
|
||||
"planned to known threat zones."
|
||||
),
|
||||
)
|
||||
# Pilots and Squadrons
|
||||
ai_pilot_levelling: bool = boolean_option(
|
||||
"Allow AI pilot leveling",
|
||||
@ -496,27 +602,14 @@ class Settings:
|
||||
max=150,
|
||||
)
|
||||
# Mission specific
|
||||
max_frontline_length: int = bounded_int_option(
|
||||
"Maximum frontline length (km)",
|
||||
max_frontline_width: int = bounded_int_option(
|
||||
"Maximum frontline width (km)",
|
||||
page=MISSION_GENERATOR_PAGE,
|
||||
section=GAMEPLAY_SECTION,
|
||||
default=80,
|
||||
min=1,
|
||||
max=100,
|
||||
)
|
||||
opfor_autoplanner_aggressiveness: int = bounded_int_option(
|
||||
"OPFOR autoplanner aggressiveness (%)",
|
||||
page=MISSION_GENERATOR_PAGE,
|
||||
section=GAMEPLAY_SECTION,
|
||||
default=20,
|
||||
min=0,
|
||||
max=100,
|
||||
detail=(
|
||||
"Chance (larger number -> higher chance) that the OPFOR AI "
|
||||
"autoplanner will take risks and plan flights against targets "
|
||||
"within threatened airspace."
|
||||
),
|
||||
)
|
||||
game_masters_count: int = bounded_int_option(
|
||||
"Number of game masters",
|
||||
page=MISSION_GENERATOR_PAGE,
|
||||
|
||||
@ -172,7 +172,7 @@ VERSION = _build_version_string()
|
||||
#: * Support for scenery objectives defined by quad zones.
|
||||
#: * Campaign designers can now define almost all settings:
|
||||
#: `settings:`
|
||||
#: ` max_frontline_length: 25` (in km)
|
||||
#: ` max_frontline_width: 25` (in km)
|
||||
#: ` perf_culling_distance: 35` (in km)
|
||||
#:
|
||||
#: Version 10.6
|
||||
|
||||
@ -77,6 +77,7 @@ def load_icons():
|
||||
"./resources/ui/misc/" + get_theme_icons() + "/money_icon.png"
|
||||
)
|
||||
ICONS["Campaign Management"] = ICONS["Money"]
|
||||
ICONS["Campaign Doctrine"] = QPixmap("./resources/ui/misc/blue-sam.png")
|
||||
ICONS["PassTurn"] = QPixmap(
|
||||
"./resources/ui/misc/" + get_theme_icons() + "/hourglass.png"
|
||||
)
|
||||
|
||||
@ -15,7 +15,7 @@ recommended_player_income_multiplier: 1.0
|
||||
recommended_enemy_income_multiplier: 1.0
|
||||
advanced_iads: false
|
||||
settings:
|
||||
max_frontline_length: 30
|
||||
max_frontline_width: 30
|
||||
player_income_multiplier: 1.5
|
||||
squadrons:
|
||||
CVN-74 John Stennis:
|
||||
|
||||
@ -15,7 +15,7 @@ recommended_player_income_multiplier: 5.0
|
||||
recommended_enemy_income_multiplier: 1.0
|
||||
advanced_iads: false
|
||||
settings:
|
||||
max_frontline_length: 30
|
||||
max_frontline_width: 30
|
||||
squadrons:
|
||||
CVN-74 John Stennis:
|
||||
- primary: BARCAP
|
||||
|
||||
@ -15,7 +15,7 @@ recommended_player_income_multiplier: 5.0
|
||||
recommended_enemy_income_multiplier: 1.0
|
||||
advanced_iads: false
|
||||
settings:
|
||||
max_frontline_length: 30
|
||||
max_frontline_width: 30
|
||||
squadrons:
|
||||
Blue CV-1:
|
||||
- primary: BARCAP
|
||||
|
||||
@ -14,7 +14,7 @@ recommended_enemy_money: 2000
|
||||
recommended_player_income_multiplier: 5.0
|
||||
recommended_enemy_income_multiplier: 1.0
|
||||
settings:
|
||||
max_frontline_length: 20
|
||||
max_frontline_width: 20
|
||||
advanced_iads: true # Campaign has connection_nodes / power_sources / command_centers
|
||||
iads_config:
|
||||
#COMMAND
|
||||
|
||||
@ -14,7 +14,7 @@ recommended_enemy_money: 2000
|
||||
recommended_player_income_multiplier: 5.0
|
||||
recommended_enemy_income_multiplier: 1.0
|
||||
settings:
|
||||
max_frontline_length: 30
|
||||
max_frontline_width: 30
|
||||
advanced_iads: true # Campaign has connection_nodes / power_sources / command_centers
|
||||
iads_config:
|
||||
#REDFOR BASE DEFENSE
|
||||
|
||||
@ -15,7 +15,7 @@ recommended_player_income_multiplier: 5.0
|
||||
recommended_enemy_income_multiplier: 1.0
|
||||
advanced_iads: false
|
||||
settings:
|
||||
max_frontline_length: 30
|
||||
max_frontline_width: 30
|
||||
squadrons:
|
||||
#Bandar Abbas Intl
|
||||
2:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user