Compare commits

...

9 Commits

Author SHA1 Message Date
Dan Albert
8c1f3e8116 Use python, not py.
py is a shortcut that launches the *latest* version of Python on the
machine. https://stackoverflow.com/a/50896577/632035

The build machines were updated to include python 3.9, so we were
doing everything with 3.9 instead of 3.8. pyproj doesn't have a binary
wheel for 3.9 on pypi yet, so we were falling back to building it from
source, which we aren't able to do, breaking the build.
2020-10-28 00:06:56 -07:00
Dan Albert
df00059d3f Fix initial frequencies for support aircraft.
Vaicom (a mod that adds voice control for the communications menus)
isn't able to follow the waypoint frequency change that normally sets
the radio channel for the AWACS/tanker flights. Set the group's
frequency correctly to start so it works.

(cherry picked from commit 4abf806837)
2020-10-17 15:56:48 -07:00
Khopa
2a3bf9821b Fixed EPLRS cherry pick merge. 2020-10-05 19:33:48 +02:00
Khopa
819d775282 EPLRS for 2.1.5 2020-10-05 19:30:43 +02:00
Khopa
efbc6fe3ae Enable EPLRS for ground units that can use it. 2020-10-05 19:29:34 +02:00
Khopa
262ba6c113 Chery picked another fix for this release, so updated changelog 2020-10-05 19:28:55 +02:00
Khopa
c41ecb6735 Fix aircrafts landing point 2020-10-05 19:27:03 +02:00
Khopa
f5c32c6b98 Version 2.1.5 2020-10-05 19:26:07 +02:00
Dan Albert
a1886e37f8 Fix save issues after aborting mission.
When the mission is aborted the pending mission is still in the event
list, which is part of the game option. That event has a reference to
the operation, which in turn contains all the mission generator
objects. Two of these objects are the radio/TACAN allocators, which
use a generator to track the next free channel. Generators cannot be
picked, so because these are transitively part of the game object the
game cannot be saved.

Aside from the briefing generator, none of those objects are
actually needed outside the generation function itself, so just make
them locals instead.

This probably needs a larger refactor at some point. It doesn't look
like we need so many calls into the operation type (it has an
initialize, a prepare, and a generate, and it doesn't seem to need
anything but the last one). The only reason breifinggen needs to
remain a part of the class is because the briefing title and
description are filled in from the derived class, where title and
description should probably be overridden properties instead. I'm also
not sure if we need to make the event list a part of game at all, and
also don't think that the mission needs to be one of these events.
2020-10-05 19:20:57 +02:00
11 changed files with 101 additions and 73 deletions

View File

@@ -18,12 +18,12 @@ jobs:
- name: Install environment
run: |
py -m venv ./venv
python -m venv ./venv
- name: Install dependencies
run: |
./venv/scripts/activate
pip install -r requirements.txt
python -m pip install -r requirements.txt
# For some reason the shiboken2.abi3.dll is not found properly, so I copy it instead
Copy-Item .\venv\Lib\site-packages\shiboken2\shiboken2.abi3.dll .\venv\Lib\site-packages\PySide2\ -Force

View File

@@ -20,12 +20,12 @@ jobs:
- name: Install environment
run: |
py -m venv ./venv
python -m venv ./venv
- name: Install dependencies
run: |
./venv/scripts/activate
pip install -r requirements.txt
python -m pip install -r requirements.txt
# For some reason the shiboken2.abi3.dll is not found properly, so I copy it instead
Copy-Item .\venv\Lib\site-packages\shiboken2\shiboken2.abi3.dll .\venv\Lib\site-packages\PySide2\ -Force

View File

@@ -1,3 +1,12 @@
# 2.1.5
## Features/Improvements :
* **[Units/Factions]** Enabled EPLRS for ground units that supports it (so they appear on A-10C II TAD and Helmet)
## Fixes :
* **[UI]** Fixed an issue that prevent saving after aborting a mission
* **[Mission Generator]** Fixed aircraft landing point type being wrong
# 2.1.4
## Fixes :

View File

@@ -68,26 +68,8 @@ class Operation:
def initialize(self, mission: Mission, conflict: Conflict):
self.current_mission = mission
self.conflict = conflict
self.radio_registry = RadioRegistry()
self.tacan_registry = TacanRegistry()
self.airgen = AircraftConflictGenerator(
mission, conflict, self.game.settings, self.game,
self.radio_registry)
self.airsupportgen = AirSupportConflictGenerator(
mission, conflict, self.game, self.radio_registry,
self.tacan_registry)
self.triggersgen = TriggersGenerator(mission, conflict, self.game)
self.visualgen = VisualGenerator(mission, conflict, self.game)
self.envgen = EnviromentGenerator(mission, conflict, self.game)
self.forcedoptionsgen = ForcedOptionsGenerator(mission, conflict, self.game)
self.groundobjectgen = GroundObjectsGenerator(
mission,
conflict,
self.game,
self.radio_registry,
self.tacan_registry
)
self.briefinggen = BriefingGenerator(mission, conflict, self.game)
self.briefinggen = BriefingGenerator(self.current_mission,
self.conflict, self.game)
def prepare(self, terrain: Terrain, is_quick: bool):
with open("resources/default_options.lua", "r") as f:
@@ -127,6 +109,9 @@ class Operation:
self.defenders_starting_position = self.to_cp.at
def generate(self):
radio_registry = RadioRegistry()
tacan_registry = TacanRegistry()
# Dedup beacon/radio frequencies, since some maps have some frequencies
# used multiple times.
beacons = load_beacons_for_terrain(self.game.theater.terrain.name)
@@ -138,7 +123,7 @@ class Operation:
logging.error(
f"TACAN beacon has no channel: {beacon.callsign}")
else:
self.tacan_registry.reserve(beacon.tacan_channel)
tacan_registry.reserve(beacon.tacan_channel)
for airfield, data in AIRFIELD_DATA.items():
if data.theater == self.game.theater.terrain.name:
@@ -150,16 +135,26 @@ class Operation:
# beacon list.
for frequency in unique_map_frequencies:
self.radio_registry.reserve(frequency)
radio_registry.reserve(frequency)
# Generate meteo
envgen = EnviromentGenerator(self.current_mission, self.conflict,
self.game)
if self.environment_settings is None:
self.environment_settings = self.envgen.generate()
self.environment_settings = envgen.generate()
else:
self.envgen.load(self.environment_settings)
envgen.load(self.environment_settings)
# Generate ground object first
self.groundobjectgen.generate()
groundobjectgen = GroundObjectsGenerator(
self.current_mission,
self.conflict,
self.game,
radio_registry,
tacan_registry
)
groundobjectgen.generate()
# Generate destroyed units
for d in self.game.get_destroyed_units():
@@ -180,11 +175,16 @@ class Operation:
dead=True,
)
# Air Support (Tanker & Awacs)
self.airsupportgen.generate(self.is_awacs_enabled)
airsupportgen = AirSupportConflictGenerator(
self.current_mission, self.conflict, self.game, radio_registry,
tacan_registry)
airsupportgen.generate(self.is_awacs_enabled)
# Generate Activity on the map
airgen = AircraftConflictGenerator(
self.current_mission, self.conflict, self.game.settings, self.game,
radio_registry)
for cp in self.game.theater.controlpoints:
side = cp.captured
if side:
@@ -192,11 +192,11 @@ class Operation:
else:
country = self.current_mission.country(self.game.enemy_country)
if cp.id in self.game.planners.keys():
self.airgen.generate_flights(
airgen.generate_flights(
cp,
country,
self.game.planners[cp.id],
self.groundobjectgen.runways
groundobjectgen.runways
)
# Generate ground units on frontline everywhere
@@ -221,18 +221,20 @@ class Operation:
self.current_mission.groundControl.red_tactical_commander = self.ca_slots
# Triggers
if self.game.is_player_attack(self.conflict.attackers_country):
cp = self.conflict.from_cp
else:
cp = self.conflict.to_cp
self.triggersgen.generate()
triggersgen = TriggersGenerator(self.current_mission, self.conflict,
self.game)
triggersgen.generate()
# Options
self.forcedoptionsgen.generate()
forcedoptionsgen = ForcedOptionsGenerator(self.current_mission,
self.conflict, self.game)
forcedoptionsgen.generate()
# Generate Visuals Smoke Effects
visualgen = VisualGenerator(self.current_mission, self.conflict,
self.game)
if self.game.settings.perf_smoke_gen:
self.visualgen.generate()
visualgen.generate()
# Inject Plugins Lua Scripts
listOfPluginsScripts = []
@@ -327,19 +329,20 @@ class Operation:
trigger.add_action(DoScript(String(lua)))
self.current_mission.triggerrules.triggers.append(trigger)
self.assign_channels_to_flights()
self.assign_channels_to_flights(airgen.flights,
airsupportgen.air_support)
kneeboard_generator = KneeboardGenerator(self.current_mission)
for dynamic_runway in self.groundobjectgen.runways.values():
for dynamic_runway in groundobjectgen.runways.values():
self.briefinggen.add_dynamic_runway(dynamic_runway)
for tanker in self.airsupportgen.air_support.tankers:
for tanker in airsupportgen.air_support.tankers:
self.briefinggen.add_tanker(tanker)
kneeboard_generator.add_tanker(tanker)
if self.is_awacs_enabled:
for awacs in self.airsupportgen.air_support.awacs:
for awacs in airsupportgen.air_support.awacs:
self.briefinggen.add_awacs(awacs)
kneeboard_generator.add_awacs(awacs)
@@ -347,21 +350,23 @@ class Operation:
self.briefinggen.add_jtac(jtac)
kneeboard_generator.add_jtac(jtac)
for flight in self.airgen.flights:
for flight in airgen.flights:
self.briefinggen.add_flight(flight)
kneeboard_generator.add_flight(flight)
self.briefinggen.generate()
kneeboard_generator.generate()
def assign_channels_to_flights(self) -> None:
def assign_channels_to_flights(self, flights: List[FlightData],
air_support: AirSupport) -> None:
"""Assigns preset radio channels for client flights."""
for flight in self.airgen.flights:
for flight in flights:
if not flight.client_units:
continue
self.assign_channels_to_flight(flight)
self.assign_channels_to_flight(flight, air_support)
def assign_channels_to_flight(self, flight: FlightData) -> None:
def assign_channels_to_flight(self, flight: FlightData,
air_support: AirSupport) -> None:
"""Assigns preset radio channels for a client flight."""
airframe = flight.aircraft_type
@@ -372,4 +377,5 @@ class Operation:
return
aircraft_data.channel_allocator.assign_channels_for_flight(
flight, self.airsupportgen.air_support)
flight, air_support
)

View File

@@ -952,6 +952,7 @@ class AircraftConflictGenerator:
# pt.tasks.append(engagetgt)
elif point.waypoint_type == FlightWaypointType.LANDING_POINT:
pt.type = "Land"
pt.action = PointAction.Landing
elif point.waypoint_type == FlightWaypointType.INGRESS_STRIKE:
if group.units[0].unit_type == B_17G:

View File

@@ -76,6 +76,7 @@ class AirSupportConflictGenerator:
speed=574,
tacanchannel=str(tacan),
)
tanker_group.set_frequency(freq.mhz)
callsign = callsign_for_support_unit(tanker_group)
tacan_callsign = {
@@ -118,6 +119,8 @@ class AirSupportConflictGenerator:
frequency=freq.mhz,
start_type=StartType.Warm,
)
awacs_flight.set_frequency(freq.mhz)
awacs_flight.points[0].tasks.append(SetInvisibleCommand(True))
awacs_flight.points[0].tasks.append(SetImmortalCommand(True))

View File

@@ -183,6 +183,11 @@ class GroundConflictGenerator:
return
for dcs_group, group in ally_groups:
if hasattr(group.units[0], 'eplrs'):
if group.units[0].eplrs:
dcs_group.points[0].tasks.append(EPLRS(dcs_group.id))
if group.role == CombatGroupRole.ARTILLERY:
# Fire on any ennemy in range
if self.game.settings.perf_artillery:

View File

@@ -80,6 +80,10 @@ class GroundObjectsGenerator:
vehicle.heading = u.heading
vehicle.player_can_drive = True
vg.add_unit(vehicle)
if hasattr(utype, 'eplrs'):
if utype.eplrs:
vg.points[0].tasks.append(EPLRS(vg.id))
else:
vg = self.m.ship_group(side, g.name, utype, position=g.position,
heading=g.units[0].heading)

2
pydcs

Submodule pydcs updated: ceea62a8e0...c203e5a1b8

View File

@@ -25,7 +25,7 @@ class ERC_90(unittype.VehicleType):
detection_range = 0
threat_range = 4000
air_weapon_dist = 4000
eprls = True
eplrs = True
class VAB__50(unittype.VehicleType):
@@ -34,7 +34,7 @@ class VAB__50(unittype.VehicleType):
detection_range = 0
threat_range = 1200
air_weapon_dist = 1200
eprls = True
eplrs = True
class VAB_T20_13(unittype.VehicleType):
@@ -43,7 +43,7 @@ class VAB_T20_13(unittype.VehicleType):
detection_range = 0
threat_range = 2000
air_weapon_dist = 2000
eprls = True
eplrs = True
class VAB_MEPHISTO(unittype.VehicleType):
@@ -52,7 +52,7 @@ class VAB_MEPHISTO(unittype.VehicleType):
detection_range = 0
threat_range = 4000
air_weapon_dist = 4000
eprls = True
eplrs = True
class VBL__50(unittype.VehicleType):
@@ -61,7 +61,7 @@ class VBL__50(unittype.VehicleType):
detection_range = 0
threat_range = 1200
air_weapon_dist = 1200
eprls = True
eplrs = True
class VBL_AANF1(unittype.VehicleType):
@@ -70,7 +70,7 @@ class VBL_AANF1(unittype.VehicleType):
detection_range = 0
threat_range = 1000
air_weapon_dist = 1000
eprls = True
eplrs = True
class VBAE_CRAB(unittype.VehicleType):
@@ -79,7 +79,7 @@ class VBAE_CRAB(unittype.VehicleType):
detection_range = 0
threat_range = 3500
air_weapon_dist = 3500
eprls = True
eplrs = True
class VBAE_CRAB_MMP(unittype.VehicleType):
@@ -88,7 +88,7 @@ class VBAE_CRAB_MMP(unittype.VehicleType):
detection_range = 0
threat_range = 3500
air_weapon_dist = 3500
eprls = True
eplrs = True
class AMX_30B2(unittype.VehicleType):
@@ -121,7 +121,7 @@ class DIM__TOYOTA_BLUE(unittype.VehicleType):
detection_range = 0
threat_range = 1200
air_weapon_dist = 1200
eprls = True
eplrs = True
class DIM__TOYOTA_GREEN(unittype.VehicleType):
@@ -130,7 +130,7 @@ class DIM__TOYOTA_GREEN(unittype.VehicleType):
detection_range = 0
threat_range = 1200
air_weapon_dist = 1200
eprls = True
eplrs = True
class DIM__TOYOTA_DESERT(unittype.VehicleType):
@@ -139,7 +139,7 @@ class DIM__TOYOTA_DESERT(unittype.VehicleType):
detection_range = 0
threat_range = 1200
air_weapon_dist = 1200
eprls = True
eplrs = True
class DIM__KAMIKAZE(unittype.VehicleType):
@@ -148,7 +148,7 @@ class DIM__KAMIKAZE(unittype.VehicleType):
detection_range = 0
threat_range = 50
air_weapon_dist = 50
eprls = True
eplrs = True
## FORTIFICATION
@@ -187,7 +187,7 @@ class TRM_2000(unittype.VehicleType):
detection_range = 3500
threat_range = 0
air_weapon_dist = 0
eprls = True
eplrs = True
class TRM_2000_Fuel(unittype.VehicleType):
id = "TRM2000_Citerne"
@@ -195,7 +195,7 @@ class TRM_2000_Fuel(unittype.VehicleType):
detection_range = 3500
threat_range = 0
air_weapon_dist = 0
eprls = True
eplrs = True
class VAB_MEDICAL(unittype.VehicleType):
id = "VABH"
@@ -203,7 +203,7 @@ class VAB_MEDICAL(unittype.VehicleType):
detection_range = 0
threat_range = 0
air_weapon_dist = 0
eprls = True
eplrs = True
class VAB(unittype.VehicleType):
id = "VAB_RADIO"
@@ -211,7 +211,7 @@ class VAB(unittype.VehicleType):
detection_range = 0
threat_range = 0
air_weapon_dist = 0
eprls = True
eplrs = True
class VBL(unittype.VehicleType):
id = "VBL-Radio"
@@ -219,7 +219,7 @@ class VBL(unittype.VehicleType):
detection_range = 0
threat_range = 0
air_weapon_dist = 0
eprls = True
eplrs = True
class Tracma_TD_1500(unittype.VehicleType):
id = "Tracma"
@@ -236,7 +236,7 @@ class SMOKE_SAM_IR(unittype.VehicleType):
detection_range = 20000
threat_range = 20000
air_weapon_dist = 20000
eprls = True
eplrs = True
class _53T2(unittype.VehicleType):
id = "AA20"
@@ -251,7 +251,7 @@ class TRM_2000_53T2(unittype.VehicleType):
detection_range = 6000
threat_range = 2000
air_weapon_dist = 2000
eprls = True
eplrs = True
class TRM_2000_PAMELA(unittype.VehicleType):
id = "TRMMISTRAL"
@@ -259,7 +259,7 @@ class TRM_2000_PAMELA(unittype.VehicleType):
detection_range = 8000
threat_range = 10000
air_weapon_dist = 10000
eprls = True
eplrs = True
## INFANTRY
@@ -285,4 +285,4 @@ class VAB_MORTIER(unittype.VehicleType):
detection_range = 0
threat_range = 15000
air_weapon_dist = 15000
eprls = True
eplrs = True

View File

@@ -8,7 +8,7 @@ from game.event import UnitsDeliveryEvent, FrontlineAttackEvent
from theater.theatergroundobject import CATEGORY_MAP
from userdata.liberation_theme import get_theme_icons
VERSION_STRING = "2.1.4"
VERSION_STRING = "2.1.5"
URLS : Dict[str, str] = {
"Manual": "https://github.com/khopa/dcs_liberation/wiki",