mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Simplfy fast forward settings, introduce ability to skip combat instead of resolving. (#3448)
This PR simplifies fast forward settings and introduces the ability to skip combat instead of resolving.
This commit is contained in:
parent
5d0ddea753
commit
df43d2eed6
@ -7,10 +7,12 @@ Saves from 11.x are not compatible with 12.0.0.
|
|||||||
* **[Engine]** Support for DCS 2.9.8.1214.
|
* **[Engine]** Support for DCS 2.9.8.1214.
|
||||||
* **[Campaign]** Flights are assigned different callsigns appropriate to the faction.
|
* **[Campaign]** Flights are assigned different callsigns appropriate to the faction.
|
||||||
* **[Campaign]** Removed deprecated settings for generating persistent and invulnerable AWACs and tankers.
|
* **[Campaign]** Removed deprecated settings for generating persistent and invulnerable AWACs and tankers.
|
||||||
|
* **[Mission Generation]** Added option to skip combat when fast forwarding, which progresses fast forward as if the combat did not occur. Simplified fast forward settings by consolidating "Fast forward mission to first contact" and "Player missions interrupt fast forward" into a single setting and expanding options for "Auto-resolve combat during fast-forward (WIP)".
|
||||||
* **[Mods]** F/A-18 E/F/G Super Hornet mod version updated to 2.3.
|
* **[Mods]** F/A-18 E/F/G Super Hornet mod version updated to 2.3.
|
||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|
||||||
|
* **[Mission Generation]** Fixed aircraft not spawning correctly on CVNs, LHAs and FARPs.
|
||||||
* **[Campaign]** Do not allow aircraft from a captured control point to retreat if the captured control point has a damaged runway.
|
* **[Campaign]** Do not allow aircraft from a captured control point to retreat if the captured control point has a damaged runway.
|
||||||
* **[Campaign]** Do not allow ground units to be transferred to LHAs, CVNs or off map spawns.
|
* **[Campaign]** Do not allow ground units to be transferred to LHAs, CVNs or off map spawns.
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,9 @@ from .atdeparture import AtDeparture
|
|||||||
from .taxi import Taxi
|
from .taxi import Taxi
|
||||||
from ..starttype import StartType
|
from ..starttype import StartType
|
||||||
|
|
||||||
|
from game.settings.settings import FastForwardStopCondition
|
||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game.ato.flight import Flight
|
from game.ato.flight import Flight
|
||||||
from game.settings import Settings
|
from game.settings import Settings
|
||||||
@ -37,7 +40,8 @@ class StartUp(AtDeparture):
|
|||||||
def should_halt_sim(self) -> bool:
|
def should_halt_sim(self) -> bool:
|
||||||
if (
|
if (
|
||||||
self.flight.client_count > 0
|
self.flight.client_count > 0
|
||||||
and self.settings.player_mission_interrupts_sim_at is StartType.COLD
|
and self.settings.fast_forward_stop_condition
|
||||||
|
== FastForwardStopCondition.PLAYER_STARTUP
|
||||||
):
|
):
|
||||||
logging.info(
|
logging.info(
|
||||||
f"Interrupting simulation because {self.flight} has players and has "
|
f"Interrupting simulation because {self.flight} has players and has "
|
||||||
|
|||||||
@ -9,6 +9,8 @@ from .navigating import Navigating
|
|||||||
from ..starttype import StartType
|
from ..starttype import StartType
|
||||||
from ...utils import LBS_TO_KG
|
from ...utils import LBS_TO_KG
|
||||||
|
|
||||||
|
from game.settings.settings import FastForwardStopCondition
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game.ato.flight import Flight
|
from game.ato.flight import Flight
|
||||||
from game.settings import Settings
|
from game.settings import Settings
|
||||||
@ -45,7 +47,8 @@ class Takeoff(AtDeparture):
|
|||||||
def should_halt_sim(self) -> bool:
|
def should_halt_sim(self) -> bool:
|
||||||
if (
|
if (
|
||||||
self.flight.client_count > 0
|
self.flight.client_count > 0
|
||||||
and self.settings.player_mission_interrupts_sim_at is StartType.RUNWAY
|
and self.settings.fast_forward_stop_condition
|
||||||
|
== FastForwardStopCondition.PLAYER_TAKEOFF
|
||||||
):
|
):
|
||||||
logging.info(
|
logging.info(
|
||||||
f"Interrupting simulation because {self.flight} has players and has "
|
f"Interrupting simulation because {self.flight} has players and has "
|
||||||
|
|||||||
@ -8,6 +8,8 @@ from .atdeparture import AtDeparture
|
|||||||
from .takeoff import Takeoff
|
from .takeoff import Takeoff
|
||||||
from ..starttype import StartType
|
from ..starttype import StartType
|
||||||
|
|
||||||
|
from game.settings.settings import FastForwardStopCondition
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game.ato.flight import Flight
|
from game.ato.flight import Flight
|
||||||
from game.settings import Settings
|
from game.settings import Settings
|
||||||
@ -37,7 +39,8 @@ class Taxi(AtDeparture):
|
|||||||
def should_halt_sim(self) -> bool:
|
def should_halt_sim(self) -> bool:
|
||||||
if (
|
if (
|
||||||
self.flight.client_count > 0
|
self.flight.client_count > 0
|
||||||
and self.settings.player_mission_interrupts_sim_at is StartType.WARM
|
and self.settings.fast_forward_stop_condition
|
||||||
|
== FastForwardStopCondition.PLAYER_TAXI
|
||||||
):
|
):
|
||||||
logging.info(
|
logging.info(
|
||||||
f"Interrupting simulation because {self.flight} has players and has "
|
f"Interrupting simulation because {self.flight} has players and has "
|
||||||
|
|||||||
@ -28,6 +28,23 @@ class AutoAtoBehavior(Enum):
|
|||||||
Prefer = "Prefer player pilots"
|
Prefer = "Prefer player pilots"
|
||||||
|
|
||||||
|
|
||||||
|
@unique
|
||||||
|
class FastForwardStopCondition(Enum):
|
||||||
|
DISABLED = "Fast forward disabled"
|
||||||
|
FIRST_CONTACT = "First contact"
|
||||||
|
PLAYER_TAKEOFF = "Player takeoff time"
|
||||||
|
PLAYER_TAXI = "Player taxi time"
|
||||||
|
PLAYER_STARTUP = "Player startup time"
|
||||||
|
MANUAL = "Manual fast forward control"
|
||||||
|
|
||||||
|
|
||||||
|
@unique
|
||||||
|
class CombatResolutionMethod(Enum):
|
||||||
|
PAUSE = "Pause simulation"
|
||||||
|
RESOLVE = "Resolve combat"
|
||||||
|
SKIP = "Skip combat"
|
||||||
|
|
||||||
|
|
||||||
DIFFICULTY_PAGE = "Difficulty"
|
DIFFICULTY_PAGE = "Difficulty"
|
||||||
|
|
||||||
AI_DIFFICULTY_SECTION = "AI Difficulty"
|
AI_DIFFICULTY_SECTION = "AI Difficulty"
|
||||||
@ -293,7 +310,7 @@ class Settings:
|
|||||||
"Tactical commander",
|
"Tactical commander",
|
||||||
page=MISSION_GENERATOR_PAGE,
|
page=MISSION_GENERATOR_PAGE,
|
||||||
section=COMMANDERS_SECTION,
|
section=COMMANDERS_SECTION,
|
||||||
default=1,
|
default=0,
|
||||||
min=0,
|
min=0,
|
||||||
max=100,
|
max=100,
|
||||||
)
|
)
|
||||||
@ -309,7 +326,7 @@ class Settings:
|
|||||||
"Observer",
|
"Observer",
|
||||||
page=MISSION_GENERATOR_PAGE,
|
page=MISSION_GENERATOR_PAGE,
|
||||||
section=COMMANDERS_SECTION,
|
section=COMMANDERS_SECTION,
|
||||||
default=1,
|
default=0,
|
||||||
min=0,
|
min=0,
|
||||||
max=100,
|
max=100,
|
||||||
)
|
)
|
||||||
@ -327,19 +344,6 @@ class Settings:
|
|||||||
"run out of fuel when players would not."
|
"run out of fuel when players would not."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
fast_forward_to_first_contact: bool = boolean_option(
|
|
||||||
"Fast forward mission to first contact (WIP)",
|
|
||||||
page=MISSION_GENERATOR_PAGE,
|
|
||||||
section=GAMEPLAY_SECTION,
|
|
||||||
default=False,
|
|
||||||
detail=(
|
|
||||||
"If enabled, the mission will be generated at the point of first contact. "
|
|
||||||
"If you enable this option, you will not be able to create new flights "
|
|
||||||
'after pressing "TAKE OFF". Doing so will create an error the next time '
|
|
||||||
'you press "TAKE OFF". Save your game first if you want to make '
|
|
||||||
"modifications."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
reload_pre_sim_checkpoint_on_abort: bool = boolean_option(
|
reload_pre_sim_checkpoint_on_abort: bool = boolean_option(
|
||||||
"Reset mission to pre-take off conditions on abort",
|
"Reset mission to pre-take off conditions on abort",
|
||||||
page=MISSION_GENERATOR_PAGE,
|
page=MISSION_GENERATOR_PAGE,
|
||||||
@ -351,37 +355,44 @@ class Settings:
|
|||||||
"your game after aborting take off."
|
"your game after aborting take off."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
player_mission_interrupts_sim_at: Optional[StartType] = choices_option(
|
fast_forward_stop_condition: FastForwardStopCondition = choices_option(
|
||||||
"Player missions interrupt fast forward",
|
"Fast forward until",
|
||||||
page=MISSION_GENERATOR_PAGE,
|
page=MISSION_GENERATOR_PAGE,
|
||||||
section=GAMEPLAY_SECTION,
|
section=GAMEPLAY_SECTION,
|
||||||
default=None,
|
default=FastForwardStopCondition.DISABLED,
|
||||||
choices={
|
choices={
|
||||||
"Never": None,
|
"No fast forward": FastForwardStopCondition.DISABLED,
|
||||||
"At startup time": StartType.COLD,
|
"Player startup time": FastForwardStopCondition.PLAYER_STARTUP,
|
||||||
"At taxi time": StartType.WARM,
|
"Player taxi time": FastForwardStopCondition.PLAYER_TAXI,
|
||||||
"At takeoff time": StartType.RUNWAY,
|
"Player takeoff time": FastForwardStopCondition.PLAYER_TAKEOFF,
|
||||||
|
"First contact": FastForwardStopCondition.FIRST_CONTACT,
|
||||||
|
"Manual": FastForwardStopCondition.MANUAL,
|
||||||
},
|
},
|
||||||
detail=(
|
detail=(
|
||||||
"Determines what player mission states will interrupt fast-forwarding to "
|
"Determines when fast forwarding stops: "
|
||||||
"first contact, if enabled. If never is selected player missions will not "
|
"No fast forward: disables fast forward. "
|
||||||
"impact simulation and player missions may be generated mid-flight. The "
|
"Player startup time: fast forward until player startup time. "
|
||||||
"other options will cause the mission to be generated as soon as a player "
|
"Player taxi time: fast forward until player taxi time. "
|
||||||
"mission reaches the set state or at first contact, whichever comes first."
|
"Player takeoff time: fast forward until player takeoff time. "
|
||||||
|
"First contact: fast forward until first contact between blue and red units. "
|
||||||
|
"Manual: manually control fast forward. Show manual controls with --show-sim-speed-controls."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
auto_resolve_combat: bool = boolean_option(
|
combat_resolution_method: CombatResolutionMethod = choices_option(
|
||||||
"Auto-resolve combat during fast-forward (WIP)",
|
"Resolve combat when fast forwarding by",
|
||||||
page=MISSION_GENERATOR_PAGE,
|
page=MISSION_GENERATOR_PAGE,
|
||||||
section=GAMEPLAY_SECTION,
|
section=GAMEPLAY_SECTION,
|
||||||
default=False,
|
default=CombatResolutionMethod.PAUSE,
|
||||||
|
choices={
|
||||||
|
"Pause": CombatResolutionMethod.PAUSE,
|
||||||
|
"Resolving combat (WIP)": CombatResolutionMethod.RESOLVE,
|
||||||
|
"Skipping combat": CombatResolutionMethod.SKIP,
|
||||||
|
},
|
||||||
detail=(
|
detail=(
|
||||||
'Requires a "Player missions interrupt fast forward" setting other than '
|
"Determines what happens when combat occurs when fast forwarding. "
|
||||||
'"Never" If enabled, aircraft entering combat during fast forward will have'
|
"Pause: pause fast forward and generate mission. Fast forwarding may stop before the condition specified in the above setting. "
|
||||||
"their combat auto-resolved after a period of time. This allows the "
|
"Resolving combat (WIP): auto resolve combat. This method is very rudimentary and will result in large losses. "
|
||||||
"simulation to advance further into the mission before requiring mission "
|
"Skipping combat: skip combat as if it did not occur."
|
||||||
"generation, but simulation is currently very rudimentary so may result in "
|
|
||||||
"huge losses."
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
supercarrier: bool = boolean_option(
|
supercarrier: bool = boolean_option(
|
||||||
|
|||||||
@ -10,6 +10,7 @@ from typing_extensions import TYPE_CHECKING
|
|||||||
from game.ato.flightstate import (
|
from game.ato.flightstate import (
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
)
|
)
|
||||||
|
from game.settings.settings import FastForwardStopCondition, CombatResolutionMethod
|
||||||
from .combat import CombatInitiator, FrozenCombat
|
from .combat import CombatInitiator, FrozenCombat
|
||||||
from .gameupdateevents import GameUpdateEvents
|
from .gameupdateevents import GameUpdateEvents
|
||||||
from .simulationresults import SimulationResults
|
from .simulationresults import SimulationResults
|
||||||
@ -32,7 +33,7 @@ class AircraftSimulation:
|
|||||||
def on_game_tick(
|
def on_game_tick(
|
||||||
self, events: GameUpdateEvents, time: datetime, duration: timedelta
|
self, events: GameUpdateEvents, time: datetime, duration: timedelta
|
||||||
) -> None:
|
) -> None:
|
||||||
if not self.game.settings.auto_resolve_combat and self.combats:
|
if not self._auto_resolve_combat() and self.combats:
|
||||||
logging.error(
|
logging.error(
|
||||||
"Cannot resume simulation because aircraft are in combat and "
|
"Cannot resume simulation because aircraft are in combat and "
|
||||||
"auto-resolve is disabled"
|
"auto-resolve is disabled"
|
||||||
@ -42,7 +43,13 @@ class AircraftSimulation:
|
|||||||
|
|
||||||
still_active = []
|
still_active = []
|
||||||
for combat in self.combats:
|
for combat in self.combats:
|
||||||
if combat.on_game_tick(time, duration, self.results, events):
|
if combat.on_game_tick(
|
||||||
|
time,
|
||||||
|
duration,
|
||||||
|
self.results,
|
||||||
|
events,
|
||||||
|
self.game.settings.combat_resolution_method,
|
||||||
|
):
|
||||||
events.end_combat(combat)
|
events.end_combat(combat)
|
||||||
else:
|
else:
|
||||||
still_active.append(combat)
|
still_active.append(combat)
|
||||||
@ -61,7 +68,7 @@ class AircraftSimulation:
|
|||||||
events.complete_simulation()
|
events.complete_simulation()
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.game.settings.auto_resolve_combat and self.combats:
|
if not self._auto_resolve_combat() and self.combats:
|
||||||
events.complete_simulation()
|
events.complete_simulation()
|
||||||
|
|
||||||
def set_initial_flight_states(self) -> None:
|
def set_initial_flight_states(self) -> None:
|
||||||
@ -80,3 +87,11 @@ class AircraftSimulation:
|
|||||||
)
|
)
|
||||||
for package in packages:
|
for package in packages:
|
||||||
yield from package.flights
|
yield from package.flights
|
||||||
|
|
||||||
|
def _auto_resolve_combat(self) -> bool:
|
||||||
|
return (
|
||||||
|
self.game.settings.fast_forward_stop_condition
|
||||||
|
!= FastForwardStopCondition.DISABLED
|
||||||
|
and self.game.settings.combat_resolution_method
|
||||||
|
!= CombatResolutionMethod.PAUSE
|
||||||
|
)
|
||||||
|
|||||||
@ -8,6 +8,7 @@ from typing import TYPE_CHECKING
|
|||||||
from shapely.ops import unary_union
|
from shapely.ops import unary_union
|
||||||
|
|
||||||
from game.ato.flightstate import InCombat, InFlight
|
from game.ato.flightstate import InCombat, InFlight
|
||||||
|
from game.settings.settings import CombatResolutionMethod
|
||||||
from game.utils import dcs_to_shapely_point
|
from game.utils import dcs_to_shapely_point
|
||||||
from .joinablecombat import JoinableCombat
|
from .joinablecombat import JoinableCombat
|
||||||
from .. import GameUpdateEvents
|
from .. import GameUpdateEvents
|
||||||
@ -67,7 +68,15 @@ class AirCombat(JoinableCombat):
|
|||||||
events: GameUpdateEvents,
|
events: GameUpdateEvents,
|
||||||
time: datetime,
|
time: datetime,
|
||||||
elapsed_time: timedelta,
|
elapsed_time: timedelta,
|
||||||
|
resolution_method: CombatResolutionMethod,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
|
if resolution_method is CombatResolutionMethod.SKIP:
|
||||||
|
for flight in self.flights:
|
||||||
|
assert isinstance(flight.state, InCombat)
|
||||||
|
flight.state.exit_combat(events, time, elapsed_time)
|
||||||
|
return
|
||||||
|
|
||||||
blue = []
|
blue = []
|
||||||
red = []
|
red = []
|
||||||
for flight in self.flights:
|
for flight in self.flights:
|
||||||
|
|||||||
@ -8,6 +8,7 @@ from typing import TYPE_CHECKING
|
|||||||
from .frozencombat import FrozenCombat
|
from .frozencombat import FrozenCombat
|
||||||
from .. import GameUpdateEvents
|
from .. import GameUpdateEvents
|
||||||
from ...ato.flightstate import InCombat
|
from ...ato.flightstate import InCombat
|
||||||
|
from game.settings.settings import CombatResolutionMethod
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from game.ato import Flight
|
from game.ato import Flight
|
||||||
@ -34,6 +35,7 @@ class AtIp(FrozenCombat):
|
|||||||
events: GameUpdateEvents,
|
events: GameUpdateEvents,
|
||||||
time: datetime,
|
time: datetime,
|
||||||
elapsed_time: timedelta,
|
elapsed_time: timedelta,
|
||||||
|
resolution_method: CombatResolutionMethod,
|
||||||
) -> None:
|
) -> None:
|
||||||
logging.debug(
|
logging.debug(
|
||||||
f"{self.flight} attack on {self.flight.package.target} auto-resolved with "
|
f"{self.flight} attack on {self.flight.package.target} auto-resolved with "
|
||||||
|
|||||||
@ -7,6 +7,7 @@ from datetime import datetime, timedelta
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from game.ato.flightstate import InCombat
|
from game.ato.flightstate import InCombat
|
||||||
|
from game.settings.settings import CombatResolutionMethod
|
||||||
from .frozencombat import FrozenCombat
|
from .frozencombat import FrozenCombat
|
||||||
from .. import GameUpdateEvents
|
from .. import GameUpdateEvents
|
||||||
|
|
||||||
@ -43,8 +44,14 @@ class DefendingSam(FrozenCombat):
|
|||||||
events: GameUpdateEvents,
|
events: GameUpdateEvents,
|
||||||
time: datetime,
|
time: datetime,
|
||||||
elapsed_time: timedelta,
|
elapsed_time: timedelta,
|
||||||
|
resolution_method: CombatResolutionMethod,
|
||||||
) -> None:
|
) -> None:
|
||||||
assert isinstance(self.flight.state, InCombat)
|
assert isinstance(self.flight.state, InCombat)
|
||||||
|
|
||||||
|
if resolution_method is CombatResolutionMethod.SKIP:
|
||||||
|
self.flight.state.exit_combat(events, time, elapsed_time)
|
||||||
|
return
|
||||||
|
|
||||||
if random.random() >= 0.5:
|
if random.random() >= 0.5:
|
||||||
logging.debug(f"Air defense combat auto-resolved with {self.flight} lost")
|
logging.debug(f"Air defense combat auto-resolved with {self.flight} lost")
|
||||||
self.flight.kill(results, events)
|
self.flight.kill(results, events)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ from datetime import datetime, timedelta
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from game.ato.flightstate import InCombat, InFlight
|
from game.ato.flightstate import InCombat, InFlight
|
||||||
|
from game.settings.settings import CombatResolutionMethod
|
||||||
from .. import GameUpdateEvents
|
from .. import GameUpdateEvents
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -26,10 +27,11 @@ class FrozenCombat(ABC):
|
|||||||
duration: timedelta,
|
duration: timedelta,
|
||||||
results: SimulationResults,
|
results: SimulationResults,
|
||||||
events: GameUpdateEvents,
|
events: GameUpdateEvents,
|
||||||
|
resolution_method: CombatResolutionMethod,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
self.elapsed_time += duration
|
self.elapsed_time += duration
|
||||||
if self.elapsed_time >= self.freeze_duration:
|
if self.elapsed_time >= self.freeze_duration:
|
||||||
self.resolve(results, events, time, self.elapsed_time)
|
self.resolve(results, events, time, self.elapsed_time, resolution_method)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -40,6 +42,7 @@ class FrozenCombat(ABC):
|
|||||||
events: GameUpdateEvents,
|
events: GameUpdateEvents,
|
||||||
time: datetime,
|
time: datetime,
|
||||||
elapsed_time: timedelta,
|
elapsed_time: timedelta,
|
||||||
|
resolution_method: CombatResolutionMethod,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
|||||||
@ -65,7 +65,7 @@ class GameLoop:
|
|||||||
self.start()
|
self.start()
|
||||||
logging.info("Running sim to first contact")
|
logging.info("Running sim to first contact")
|
||||||
while not self.completed:
|
while not self.completed:
|
||||||
self.tick(suppress_events=True)
|
self.tick(suppress_events=False)
|
||||||
|
|
||||||
def pause_and_generate_miz(self, output: Path) -> None:
|
def pause_and_generate_miz(self, output: Path) -> None:
|
||||||
self.pause()
|
self.pause()
|
||||||
|
|||||||
@ -16,6 +16,7 @@ from game import Game, persistence
|
|||||||
from game.ato.package import Package
|
from game.ato.package import Package
|
||||||
from game.ato.traveltime import TotEstimator
|
from game.ato.traveltime import TotEstimator
|
||||||
from game.profiling import logged_duration
|
from game.profiling import logged_duration
|
||||||
|
from game.settings.settings import FastForwardStopCondition
|
||||||
from game.utils import meters
|
from game.utils import meters
|
||||||
from qt_ui.models import GameModel
|
from qt_ui.models import GameModel
|
||||||
from qt_ui.simcontroller import SimController
|
from qt_ui.simcontroller import SimController
|
||||||
@ -248,50 +249,6 @@ class QTopPanel(QFrame):
|
|||||||
mbox.exec_()
|
mbox.exec_()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def check_valid_autoresolve_settings(self) -> bool:
|
|
||||||
if not self.game.settings.fast_forward_to_first_contact:
|
|
||||||
return True
|
|
||||||
|
|
||||||
if not self.game.settings.auto_resolve_combat:
|
|
||||||
return True
|
|
||||||
|
|
||||||
has_clients = self.ato_has_clients()
|
|
||||||
if (
|
|
||||||
has_clients
|
|
||||||
and self.game.settings.player_mission_interrupts_sim_at is not None
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
|
|
||||||
if has_clients:
|
|
||||||
message = textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
You have enabled settings to fast forward and to auto-resolve combat,
|
|
||||||
but have not selected any interrupt condition. Fast forward will never
|
|
||||||
stop with your current settings. To use auto- resolve, you must choose a
|
|
||||||
"Player missions interrupt fast forward" setting other than "Never".
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
message = textwrap.dedent(
|
|
||||||
"""\
|
|
||||||
You have enabled settings to fast forward and to auto-resolve combat,
|
|
||||||
but have no players. Fast forward will never stop with your current
|
|
||||||
settings. Auto-resolve and fast forward cannot be used without player
|
|
||||||
flights and a "Player missions interrupt fast forward" setting other
|
|
||||||
than "Never".
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
|
|
||||||
mbox = QMessageBox(
|
|
||||||
QMessageBox.Icon.Critical,
|
|
||||||
"Incompatible fast-forward settings",
|
|
||||||
message,
|
|
||||||
parent=self,
|
|
||||||
)
|
|
||||||
mbox.setEscapeButton(mbox.addButton(QMessageBox.StandardButton.Close))
|
|
||||||
mbox.exec()
|
|
||||||
return False
|
|
||||||
|
|
||||||
def launch_mission(self):
|
def launch_mission(self):
|
||||||
"""Finishes planning and waits for mission completion."""
|
"""Finishes planning and waits for mission completion."""
|
||||||
if not self.ato_has_clients() and not self.confirm_no_client_launch():
|
if not self.ato_has_clients() and not self.confirm_no_client_launch():
|
||||||
@ -307,10 +264,10 @@ class QTopPanel(QFrame):
|
|||||||
if not self.confirm_negative_start_time(negative_starts):
|
if not self.confirm_negative_start_time(negative_starts):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.check_valid_autoresolve_settings():
|
if self.game.settings.fast_forward_stop_condition not in [
|
||||||
return
|
FastForwardStopCondition.DISABLED,
|
||||||
|
FastForwardStopCondition.MANUAL,
|
||||||
if self.game.settings.fast_forward_to_first_contact:
|
]:
|
||||||
with logged_duration("Simulating to first contact"):
|
with logged_duration("Simulating to first contact"):
|
||||||
self.sim_controller.run_to_first_contact()
|
self.sim_controller.run_to_first_contact()
|
||||||
self.sim_controller.generate_miz(
|
self.sim_controller.generate_miz(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user