mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Will now generate control point trigger zones and AI aircraft for the Pretense campaign.
This commit is contained in:
parent
8402e5d9bb
commit
db95fc17dc
@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import random
|
||||
from datetime import datetime
|
||||
from functools import cached_property
|
||||
from typing import Any, Dict, List, TYPE_CHECKING, Tuple
|
||||
@ -33,18 +34,17 @@ from game.theater.controlpoint import (
|
||||
Fob,
|
||||
)
|
||||
from game.unitmap import UnitMap
|
||||
from .aircraftpainter import AircraftPainter
|
||||
from .flightdata import FlightData
|
||||
from .flightgroupconfigurator import FlightGroupConfigurator
|
||||
from .flightgroupspawner import FlightGroupSpawner
|
||||
from ...data.weapons import WeaponType
|
||||
from game.missiongenerator.aircraft.aircraftpainter import AircraftPainter
|
||||
from game.missiongenerator.aircraft.flightdata import FlightData
|
||||
from game.missiongenerator.aircraft.flightgroupspawner import FlightGroupSpawner
|
||||
from game.data.weapons import WeaponType
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
from game.squadrons import Squadron
|
||||
|
||||
|
||||
class AircraftGenerator:
|
||||
class PretenseAircraftGenerator:
|
||||
def __init__(
|
||||
self,
|
||||
mission: Mission,
|
||||
@ -101,6 +101,7 @@ class AircraftGenerator:
|
||||
def generate_flights(
|
||||
self,
|
||||
country: Country,
|
||||
cp: ControlPoint,
|
||||
ato: AirTaskingOrder,
|
||||
dynamic_runways: Dict[str, RunwayData],
|
||||
) -> None:
|
||||
@ -115,6 +116,61 @@ class AircraftGenerator:
|
||||
ato: The ATO to spawn aircraft for.
|
||||
dynamic_runways: Runway data for carriers and FARPs.
|
||||
"""
|
||||
|
||||
num_of_sead = 0
|
||||
num_of_cas = 0
|
||||
num_of_strike = 0
|
||||
num_of_cap = 0
|
||||
for squadron in cp.squadrons:
|
||||
squadron.owned_aircraft += 1
|
||||
squadron.untasked_aircraft += 1
|
||||
package = Package(cp, squadron.flight_db, auto_asap=False)
|
||||
mission_types = squadron.auto_assignable_mission_types
|
||||
if (
|
||||
FlightType.TRANSPORT in mission_types
|
||||
or FlightType.AIR_ASSAULT in mission_types
|
||||
):
|
||||
flight_type = FlightType.TRANSPORT
|
||||
elif (
|
||||
FlightType.SEAD in mission_types
|
||||
or FlightType.SEAD_SWEEP
|
||||
or FlightType.SEAD_ESCORT in mission_types
|
||||
) and num_of_sead < 2:
|
||||
flight_type = FlightType.SEAD
|
||||
num_of_sead += 1
|
||||
elif FlightType.DEAD in mission_types and num_of_sead < 2:
|
||||
flight_type = FlightType.DEAD
|
||||
num_of_sead += 1
|
||||
elif (
|
||||
FlightType.CAS in mission_types or FlightType.BAI in mission_types
|
||||
) and num_of_cas < 2:
|
||||
flight_type = FlightType.CAS
|
||||
num_of_cas += 1
|
||||
elif (
|
||||
FlightType.STRIKE in mission_types
|
||||
or FlightType.OCA_RUNWAY in mission_types
|
||||
or FlightType.OCA_AIRCRAFT in mission_types
|
||||
) and num_of_strike < 2:
|
||||
flight_type = FlightType.STRIKE
|
||||
num_of_strike += 1
|
||||
elif (
|
||||
FlightType.BARCAP in mission_types
|
||||
or FlightType.TARCAP in mission_types
|
||||
or FlightType.ESCORT in mission_types
|
||||
) and num_of_cap < 2:
|
||||
flight_type = FlightType.BARCAP
|
||||
num_of_cap += 1
|
||||
else:
|
||||
flight_type = random.choice(list(mission_types))
|
||||
flight = Flight(
|
||||
package, squadron, 1, flight_type, StartType.COLD, divert=cp
|
||||
)
|
||||
flight.state = WaitingForStart(
|
||||
flight, self.game.settings, self.game.conditions.start_time
|
||||
)
|
||||
package.add_flight(flight)
|
||||
ato.add_package(package)
|
||||
|
||||
self._reserve_frequencies_and_tacan(ato)
|
||||
|
||||
for package in reversed(sorted(ato.packages, key=lambda x: x.time_over_target)):
|
||||
@ -134,103 +190,6 @@ class AircraftGenerator:
|
||||
flight, country, dynamic_runways
|
||||
)
|
||||
self.unit_map.add_aircraft(group, flight)
|
||||
if (
|
||||
package.primary_flight is not None
|
||||
and package.primary_flight.flight_plan.is_formation(
|
||||
package.primary_flight.flight_plan
|
||||
)
|
||||
):
|
||||
splittrigger = TriggerOnce(Event.NoEvent, f"Split-{id(package)}")
|
||||
splittrigger.add_condition(FlagIsTrue(flag=f"split-{id(package)}"))
|
||||
splittrigger.add_condition(Or())
|
||||
splittrigger.add_condition(FlagIsFalse(flag=f"split-{id(package)}"))
|
||||
splittrigger.add_condition(GroupDead(package.primary_flight.group_id))
|
||||
for flight in package.flights:
|
||||
if flight.flight_type in [
|
||||
FlightType.ESCORT,
|
||||
FlightType.SEAD_ESCORT,
|
||||
]:
|
||||
splittrigger.add_action(AITaskPush(flight.group_id, 1))
|
||||
if len(splittrigger.actions) > 0:
|
||||
self.mission.triggerrules.triggers.append(splittrigger)
|
||||
|
||||
def spawn_unused_aircraft(
|
||||
self, player_country: Country, enemy_country: Country
|
||||
) -> None:
|
||||
for control_point in self.game.theater.controlpoints:
|
||||
if not (
|
||||
isinstance(control_point, Airfield) or isinstance(control_point, Fob)
|
||||
):
|
||||
continue
|
||||
|
||||
if control_point.captured:
|
||||
country = player_country
|
||||
else:
|
||||
country = enemy_country
|
||||
|
||||
for squadron in control_point.squadrons:
|
||||
try:
|
||||
self._spawn_unused_for(squadron, country)
|
||||
except NoParkingSlotError:
|
||||
# If we run out of parking, stop spawning aircraft at this base.
|
||||
break
|
||||
|
||||
def _spawn_unused_for(self, squadron: Squadron, country: Country) -> None:
|
||||
assert isinstance(squadron.location, Airfield) or isinstance(
|
||||
squadron.location, Fob
|
||||
)
|
||||
if (
|
||||
squadron.coalition.player
|
||||
and self.game.settings.perf_disable_untasked_blufor_aircraft
|
||||
):
|
||||
return
|
||||
elif (
|
||||
not squadron.coalition.player
|
||||
and self.game.settings.perf_disable_untasked_opfor_aircraft
|
||||
):
|
||||
return
|
||||
|
||||
for _ in range(squadron.untasked_aircraft):
|
||||
# Creating a flight even those this isn't a fragged mission lets us
|
||||
# reuse the existing debriefing code.
|
||||
# TODO: Special flight type?
|
||||
flight = Flight(
|
||||
Package(squadron.location, self.game.db.flights),
|
||||
squadron,
|
||||
1,
|
||||
FlightType.BARCAP,
|
||||
StartType.COLD,
|
||||
divert=None,
|
||||
claim_inv=False,
|
||||
)
|
||||
flight.state = Completed(flight, self.game.settings)
|
||||
|
||||
group = FlightGroupSpawner(
|
||||
flight,
|
||||
country,
|
||||
self.mission,
|
||||
self.helipads,
|
||||
self.ground_spawns_roadbase,
|
||||
self.ground_spawns,
|
||||
self.mission_data,
|
||||
).create_idle_aircraft()
|
||||
if group:
|
||||
if (
|
||||
not squadron.coalition.player
|
||||
and squadron.aircraft.flyable
|
||||
and (
|
||||
self.game.settings.enable_squadron_pilot_limits
|
||||
or squadron.number_of_available_pilots > 0
|
||||
)
|
||||
and self.game.settings.untasked_opfor_client_slots
|
||||
):
|
||||
flight.state = WaitingForStart(
|
||||
flight, self.game.settings, self.game.conditions.start_time
|
||||
)
|
||||
group.uncontrolled = False
|
||||
group.units[0].skill = Skill.Client
|
||||
AircraftPainter(flight, group).apply_livery()
|
||||
self.unit_map.add_aircraft(group, flight)
|
||||
|
||||
def create_and_configure_flight(
|
||||
self, flight: Flight, country: Country, dynamic_runways: Dict[str, RunwayData]
|
||||
@ -245,21 +204,21 @@ class AircraftGenerator:
|
||||
self.ground_spawns,
|
||||
self.mission_data,
|
||||
).create_flight_group()
|
||||
self.flights.append(
|
||||
FlightGroupConfigurator(
|
||||
flight,
|
||||
group,
|
||||
self.game,
|
||||
self.mission,
|
||||
self.time,
|
||||
self.radio_registry,
|
||||
self.tacan_registy,
|
||||
self.laser_code_registry,
|
||||
self.mission_data,
|
||||
dynamic_runways,
|
||||
self.use_client,
|
||||
).configure()
|
||||
)
|
||||
# self.flights.append(
|
||||
# FlightGroupConfigurator(
|
||||
# flight,
|
||||
# group,
|
||||
# self.game,
|
||||
# self.mission,
|
||||
# self.time,
|
||||
# self.radio_registry,
|
||||
# self.tacan_registy,
|
||||
# self.laser_code_registry,
|
||||
# self.mission_data,
|
||||
# dynamic_runways,
|
||||
# self.use_client,
|
||||
# ).configure()
|
||||
# )
|
||||
|
||||
if self.ewrj:
|
||||
self._track_ewrj_flight(flight, group)
|
||||
|
||||
@ -6,6 +6,7 @@ from pathlib import Path
|
||||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
import dcs.lua
|
||||
from dataclasses import field
|
||||
from dcs import Mission, Point
|
||||
from dcs.coalition import Coalition
|
||||
from dcs.countries import country_dict
|
||||
@ -13,38 +14,40 @@ from dcs.task import OptReactOnThreat
|
||||
|
||||
from game.atcdata import AtcData
|
||||
from game.dcs.beacons import Beacons
|
||||
from game.dcs.helpers import unit_type_from_name
|
||||
from game.missiongenerator.aircraft.aircraftgenerator import (
|
||||
AircraftGenerator,
|
||||
)
|
||||
|
||||
from game.naming import namegen
|
||||
from game.radio.radios import RadioFrequency, RadioRegistry, MHz
|
||||
from game.radio.tacan import TacanRegistry
|
||||
from game.theater import Airfield
|
||||
from game.theater.bullseye import Bullseye
|
||||
from game.unitmap import UnitMap
|
||||
from .briefinggenerator import BriefingGenerator, MissionInfoGenerator
|
||||
from .cargoshipgenerator import CargoShipGenerator
|
||||
from .convoygenerator import ConvoyGenerator
|
||||
from .drawingsgenerator import DrawingsGenerator
|
||||
from .environmentgenerator import EnvironmentGenerator
|
||||
from .flotgenerator import FlotGenerator
|
||||
from .forcedoptionsgenerator import ForcedOptionsGenerator
|
||||
from .frontlineconflictdescription import FrontLineConflictDescription
|
||||
from .kneeboard import KneeboardGenerator
|
||||
from .lasercoderegistry import LaserCodeRegistry
|
||||
from .luagenerator import LuaGenerator
|
||||
from .missiondata import MissionData
|
||||
from .tgogenerator import TgoGenerator
|
||||
from .triggergenerator import TriggerGenerator
|
||||
from .visualsgenerator import VisualsGenerator
|
||||
from game.pretense.pretenseaircraftgenerator import PretenseAircraftGenerator
|
||||
from game.missiongenerator.briefinggenerator import (
|
||||
BriefingGenerator,
|
||||
MissionInfoGenerator,
|
||||
)
|
||||
from game.missiongenerator.convoygenerator import ConvoyGenerator
|
||||
from game.missiongenerator.environmentgenerator import EnvironmentGenerator
|
||||
from game.missiongenerator.flotgenerator import FlotGenerator
|
||||
from game.missiongenerator.forcedoptionsgenerator import ForcedOptionsGenerator
|
||||
from game.missiongenerator.frontlineconflictdescription import (
|
||||
FrontLineConflictDescription,
|
||||
)
|
||||
from game.missiongenerator.kneeboard import KneeboardGenerator
|
||||
from game.missiongenerator.lasercoderegistry import LaserCodeRegistry
|
||||
from game.missiongenerator.luagenerator import LuaGenerator
|
||||
from game.missiongenerator.missiondata import MissionData
|
||||
from game.missiongenerator.tgogenerator import TgoGenerator
|
||||
from .pretensetriggergenerator import PretenseTriggerGenerator
|
||||
from game.missiongenerator.visualsgenerator import VisualsGenerator
|
||||
from ..ato import Flight
|
||||
from ..radio.TacanContainer import TacanContainer
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
|
||||
|
||||
class MissionGenerator:
|
||||
class PretenseMissionGenerator:
|
||||
def __init__(self, game: Game, time: datetime) -> None:
|
||||
self.game = game
|
||||
self.time = time
|
||||
@ -94,20 +97,16 @@ class MissionGenerator:
|
||||
tgo_generator.generate()
|
||||
|
||||
ConvoyGenerator(self.mission, self.game, self.unit_map).generate()
|
||||
CargoShipGenerator(self.mission, self.game, self.unit_map).generate()
|
||||
|
||||
self.generate_destroyed_units()
|
||||
|
||||
# Generate ground conflicts first so the JTACs get the first laser code (1688)
|
||||
# rather than the first player flight with a TGP.
|
||||
self.generate_ground_conflicts()
|
||||
self.generate_air_units(tgo_generator)
|
||||
|
||||
TriggerGenerator(self.mission, self.game).generate()
|
||||
PretenseTriggerGenerator(self.mission, self.game).generate()
|
||||
ForcedOptionsGenerator(self.mission, self.game).generate()
|
||||
VisualsGenerator(self.mission, self.game).generate()
|
||||
LuaGenerator(self.game, self.mission, self.mission_data).generate()
|
||||
DrawingsGenerator(self.mission, self.game).generate()
|
||||
|
||||
self.setup_combined_arms()
|
||||
|
||||
@ -119,22 +118,6 @@ class MissionGenerator:
|
||||
|
||||
return self.unit_map
|
||||
|
||||
@staticmethod
|
||||
def _configure_ewrj(gen: AircraftGenerator) -> None:
|
||||
for groups in gen.ewrj_package_dict.values():
|
||||
optrot = groups[0].points[0].tasks[0]
|
||||
assert isinstance(optrot, OptReactOnThreat)
|
||||
if (
|
||||
len(groups) == 1
|
||||
and optrot.value != OptReactOnThreat.Values.PassiveDefense
|
||||
):
|
||||
# primary flight with no EWR-Jamming capability
|
||||
continue
|
||||
for group in groups:
|
||||
group.points[0].tasks[0] = OptReactOnThreat(
|
||||
OptReactOnThreat.Values.PassiveDefense
|
||||
)
|
||||
|
||||
def setup_mission_coalitions(self) -> None:
|
||||
self.mission.coalition["blue"] = Coalition(
|
||||
"blue", bullseye=self.game.blue.bullseye.to_pydcs()
|
||||
@ -232,7 +215,7 @@ class MissionGenerator:
|
||||
"""Generate the air units for the Operation"""
|
||||
|
||||
# Generate Aircraft Activity on the map
|
||||
aircraft_generator = AircraftGenerator(
|
||||
aircraft_generator = PretenseAircraftGenerator(
|
||||
self.mission,
|
||||
self.game.settings,
|
||||
self.game,
|
||||
@ -247,22 +230,25 @@ class MissionGenerator:
|
||||
ground_spawns=tgo_generator.ground_spawns,
|
||||
)
|
||||
|
||||
# Clear parking slots and ATOs
|
||||
aircraft_generator.clear_parking_slots()
|
||||
self.game.blue.ato.clear()
|
||||
self.game.red.ato.clear()
|
||||
|
||||
aircraft_generator.generate_flights(
|
||||
self.p_country,
|
||||
self.game.blue.ato,
|
||||
tgo_generator.runways,
|
||||
)
|
||||
aircraft_generator.generate_flights(
|
||||
self.e_country,
|
||||
self.game.red.ato,
|
||||
tgo_generator.runways,
|
||||
)
|
||||
aircraft_generator.spawn_unused_aircraft(
|
||||
self.p_country,
|
||||
self.e_country,
|
||||
)
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if cp.captured:
|
||||
ato = self.game.blue.ato
|
||||
cp_country = self.p_country
|
||||
else:
|
||||
ato = self.game.red.ato
|
||||
cp_country = self.e_country
|
||||
print(f"Generating flights for {cp_country.name} at {cp}")
|
||||
aircraft_generator.generate_flights(
|
||||
cp_country,
|
||||
cp,
|
||||
ato,
|
||||
tgo_generator.runways,
|
||||
)
|
||||
|
||||
self.mission_data.flights = aircraft_generator.flights
|
||||
|
||||
@ -274,35 +260,6 @@ class MissionGenerator:
|
||||
if self.game.settings.plugins.get("ewrj"):
|
||||
self._configure_ewrj(aircraft_generator)
|
||||
|
||||
def generate_destroyed_units(self) -> None:
|
||||
"""Add destroyed units to the Mission"""
|
||||
if not self.game.settings.perf_destroyed_units:
|
||||
return
|
||||
|
||||
for d in self.game.get_destroyed_units():
|
||||
try:
|
||||
type_name = d["type"]
|
||||
if not isinstance(type_name, str):
|
||||
raise TypeError(
|
||||
"Expected the type of the destroyed static to be a string"
|
||||
)
|
||||
utype = unit_type_from_name(type_name)
|
||||
except KeyError:
|
||||
logging.warning(f"Destroyed unit has no type: {d}")
|
||||
continue
|
||||
|
||||
pos = Point(cast(float, d["x"]), cast(float, d["z"]), self.mission.terrain)
|
||||
if utype is not None and not self.game.position_culled(pos):
|
||||
self.mission.static_group(
|
||||
country=self.p_country,
|
||||
name="",
|
||||
_type=utype,
|
||||
hidden=True,
|
||||
position=pos,
|
||||
heading=d["orientation"],
|
||||
dead=True,
|
||||
)
|
||||
|
||||
def notify_info_generators(
|
||||
self,
|
||||
) -> None:
|
||||
|
||||
@ -56,7 +56,7 @@ class Silence(Option):
|
||||
Key = 7
|
||||
|
||||
|
||||
class TriggerGenerator:
|
||||
class PretenseTriggerGenerator:
|
||||
capture_zone_types = (Fob, Airfield)
|
||||
capture_zone_flag = 600
|
||||
|
||||
@ -146,38 +146,7 @@ class TriggerGenerator:
|
||||
v += 1
|
||||
self.mission.triggerrules.triggers.append(mark_trigger)
|
||||
|
||||
def _generate_clear_statics_trigger(self, scenery_clear_zones: List[Point]) -> None:
|
||||
for zone_center in scenery_clear_zones:
|
||||
trigger_zone = self.mission.triggers.add_triggerzone(
|
||||
zone_center,
|
||||
radius=TRIGGER_RADIUS_CLEAR_SCENERY,
|
||||
hidden=False,
|
||||
name="CLEAR",
|
||||
)
|
||||
clear_trigger = TriggerCondition(Event.NoEvent, "Clear Trigger")
|
||||
clear_flag = self.get_capture_zone_flag()
|
||||
clear_trigger.add_condition(TimeSinceFlag(clear_flag, 30))
|
||||
clear_trigger.add_action(ClearFlag(clear_flag))
|
||||
clear_trigger.add_action(SetFlag(clear_flag))
|
||||
clear_trigger.add_action(
|
||||
RemoveSceneObjects(
|
||||
objects_mask=RemoveSceneObjectsMask.OBJECTS_ONLY,
|
||||
zone=trigger_zone.id,
|
||||
)
|
||||
)
|
||||
clear_trigger.add_action(
|
||||
SceneryDestructionZone(destruction_level=100, zone=trigger_zone.id)
|
||||
)
|
||||
self.mission.triggerrules.triggers.append(clear_trigger)
|
||||
|
||||
enable_clear_trigger = TriggerOnce(Event.NoEvent, "Enable Clear Trigger")
|
||||
enable_clear_trigger.add_condition(TimeAfter(30))
|
||||
enable_clear_trigger.add_action(ClearFlag(clear_flag))
|
||||
enable_clear_trigger.add_action(SetFlag(clear_flag))
|
||||
# clear_trigger.add_action(MessageToAll(text=String("Enable clear trigger"),))
|
||||
self.mission.triggerrules.triggers.append(enable_clear_trigger)
|
||||
|
||||
def _generate_capture_triggers(
|
||||
def _generate_pretense_zone_triggers(
|
||||
self, player_coalition: str, enemy_coalition: str
|
||||
) -> None:
|
||||
"""Creates a pair of triggers for each control point of `cls.capture_zone_types`.
|
||||
@ -185,62 +154,16 @@ class TriggerGenerator:
|
||||
Directly appends to the global `base_capture_events` var declared by `dcs_libaration.lua`
|
||||
"""
|
||||
for cp in self.game.theater.controlpoints:
|
||||
if isinstance(cp, self.capture_zone_types) and not cp.is_carrier:
|
||||
if cp.captured:
|
||||
attacking_coalition = enemy_coalition
|
||||
attack_coalition_int = 1 # 1 is the Event int for Red
|
||||
defending_coalition = player_coalition
|
||||
defend_coalition_int = 2 # 2 is the Event int for Blue
|
||||
else:
|
||||
attacking_coalition = player_coalition
|
||||
attack_coalition_int = 2
|
||||
defending_coalition = enemy_coalition
|
||||
defend_coalition_int = 1
|
||||
if isinstance(cp, self.capture_zone_types) and not cp.is_fleet:
|
||||
|
||||
zone_color = {1: 0.0, 2: 0.0, 3: 0.0, 4: 0.149}
|
||||
trigger_zone = self.mission.triggers.add_triggerzone(
|
||||
cp.position,
|
||||
radius=TRIGGER_RADIUS_CAPTURE,
|
||||
hidden=False,
|
||||
name="CAPTURE",
|
||||
name=cp.name,
|
||||
color=zone_color,
|
||||
)
|
||||
flag = self.get_capture_zone_flag()
|
||||
capture_trigger = TriggerCondition(Event.NoEvent, "Capture Trigger")
|
||||
capture_trigger.add_condition(
|
||||
AllOfCoalitionOutsideZone(
|
||||
defending_coalition, trigger_zone.id, unit_type="GROUND"
|
||||
)
|
||||
)
|
||||
capture_trigger.add_condition(
|
||||
PartOfCoalitionInZone(
|
||||
attacking_coalition, trigger_zone.id, unit_type="GROUND"
|
||||
)
|
||||
)
|
||||
capture_trigger.add_condition(FlagIsFalse(flag=flag))
|
||||
script_string = String(
|
||||
f'base_capture_events[#base_capture_events + 1] = "{cp.id}||{attack_coalition_int}||{cp.full_name}"'
|
||||
)
|
||||
capture_trigger.add_action(DoScript(script_string))
|
||||
capture_trigger.add_action(SetFlag(flag=flag))
|
||||
self.mission.triggerrules.triggers.append(capture_trigger)
|
||||
|
||||
recapture_trigger = TriggerCondition(Event.NoEvent, "Capture Trigger")
|
||||
recapture_trigger.add_condition(
|
||||
AllOfCoalitionOutsideZone(
|
||||
attacking_coalition, trigger_zone.id, unit_type="GROUND"
|
||||
)
|
||||
)
|
||||
recapture_trigger.add_condition(
|
||||
PartOfCoalitionInZone(
|
||||
defending_coalition, trigger_zone.id, unit_type="GROUND"
|
||||
)
|
||||
)
|
||||
recapture_trigger.add_condition(FlagIsTrue(flag=flag))
|
||||
script_string = String(
|
||||
f'base_capture_events[#base_capture_events + 1] = "{cp.id}||{defend_coalition_int}||{cp.full_name}"'
|
||||
)
|
||||
recapture_trigger.add_action(DoScript(script_string))
|
||||
recapture_trigger.add_action(ClearFlag(flag=flag))
|
||||
self.mission.triggerrules.triggers.append(recapture_trigger)
|
||||
|
||||
def generate(self) -> None:
|
||||
player_coalition = "blue"
|
||||
@ -249,13 +172,7 @@ class TriggerGenerator:
|
||||
self._set_skill(player_coalition, enemy_coalition)
|
||||
self._set_allegiances(player_coalition, enemy_coalition)
|
||||
self._gen_markers()
|
||||
self._generate_capture_triggers(player_coalition, enemy_coalition)
|
||||
if self.game.settings.ground_start_scenery_remove_triggers:
|
||||
try:
|
||||
self._generate_clear_statics_trigger(self.game.scenery_clear_zones)
|
||||
self.game.scenery_clear_zones.clear()
|
||||
except AttributeError:
|
||||
logging.info(f"Unable to create Clear Statics triggers")
|
||||
self._generate_pretense_zone_triggers(player_coalition, enemy_coalition)
|
||||
|
||||
@classmethod
|
||||
def get_capture_zone_flag(cls) -> int:
|
||||
|
||||
@ -32,6 +32,7 @@ def load_icons():
|
||||
"./resources/ui/misc/" + get_theme_icons() + "/github.png"
|
||||
)
|
||||
ICONS["Ukraine"] = QPixmap("./resources/ui/misc/ukraine.png")
|
||||
ICONS["Pretense"] = QPixmap("./resources/ui/misc/pretense.png")
|
||||
|
||||
ICONS["Control Points"] = QPixmap(
|
||||
"./resources/ui/misc/" + get_theme_icons() + "/circle.png"
|
||||
|
||||
@ -21,6 +21,7 @@ from game import Game, VERSION, persistency, Migrator
|
||||
from game.debriefing import Debriefing
|
||||
from game.game import TurnState
|
||||
from game.layout import LAYOUTS
|
||||
from game.pretense.pretensemissiongenerator import PretenseMissionGenerator
|
||||
from game.server import EventStream, GameContext
|
||||
from game.server.dependencies import QtCallbacks, QtContext
|
||||
from game.theater import ControlPoint, MissionTarget, TheaterGroundObject
|
||||
@ -41,6 +42,7 @@ from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
|
||||
from qt_ui.windows.infos.QInfoPanel import QInfoPanel
|
||||
from qt_ui.windows.logs.QLogsWindow import QLogsWindow
|
||||
from qt_ui.windows.newgame.QNewGameWizard import NewGameWizard
|
||||
from qt_ui.windows.newgame.QNewPretenseWizard import NewPretenseWizard
|
||||
from qt_ui.windows.notes.QNotesWindow import QNotesWindow
|
||||
from qt_ui.windows.preferences.QLiberationPreferencesWindow import (
|
||||
QLiberationPreferencesWindow,
|
||||
@ -193,6 +195,10 @@ class QLiberationWindow(QMainWindow):
|
||||
lambda: webbrowser.open_new_tab("https://shdwp.github.io/ukraine/")
|
||||
)
|
||||
|
||||
self.newPretenseAction = QAction("&New Pretense Campaign", self)
|
||||
self.newPretenseAction.setIcon(QIcon(CONST.ICONS["Pretense"]))
|
||||
self.newPretenseAction.triggered.connect(self.newPretenseCampaign)
|
||||
|
||||
self.openLogsAction = QAction("Show &logs", self)
|
||||
self.openLogsAction.triggered.connect(self.showLogsDialog)
|
||||
|
||||
@ -234,6 +240,7 @@ class QLiberationWindow(QMainWindow):
|
||||
self.links_bar.addAction(self.openDiscordAction)
|
||||
self.links_bar.addAction(self.openGithubAction)
|
||||
self.links_bar.addAction(self.ukraineAction)
|
||||
self.links_bar.addAction(self.newPretenseAction)
|
||||
|
||||
self.actions_bar = self.addToolBar("Actions")
|
||||
self.actions_bar.addAction(self.openSettingsAction)
|
||||
@ -303,6 +310,15 @@ class QLiberationWindow(QMainWindow):
|
||||
wizard.show()
|
||||
wizard.accepted.connect(lambda: self.onGameGenerated(wizard.generatedGame))
|
||||
|
||||
def newPretenseCampaign(self):
|
||||
output = persistency.mission_path_for("pretense_campaign.miz")
|
||||
PretenseMissionGenerator(
|
||||
self.game, self.game.conditions.start_time
|
||||
).generate_miz(output)
|
||||
title = "Pretense campaign generated"
|
||||
msg = f"A Pretense campaign mission has been successfully generated in {output}"
|
||||
QMessageBox.information(QApplication.focusWidget(), title, msg, QMessageBox.Ok)
|
||||
|
||||
def openFile(self):
|
||||
if self.game is not None and self.game.savepath:
|
||||
save_dir = self.game.savepath
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user