mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
add support for neutral FOBs
This commit is contained in:
parent
9f10ecc884
commit
c0748e2a3e
@ -57,6 +57,7 @@ class MizCampaignLoader:
|
|||||||
FOB_UNIT_TYPE = Unarmed.SKP_11.id
|
FOB_UNIT_TYPE = Unarmed.SKP_11.id
|
||||||
FARP_HELIPADS_TYPE = ["Invisible FARP", "SINGLE_HELIPAD", "FARP"]
|
FARP_HELIPADS_TYPE = ["Invisible FARP", "SINGLE_HELIPAD", "FARP"]
|
||||||
INVISIBLE_FOB_UNIT_TYPE = Unarmed.M_818.id
|
INVISIBLE_FOB_UNIT_TYPE = Unarmed.M_818.id
|
||||||
|
NEUTRAL_FOB_UNIT_TYPE = Unarmed.KrAZ6322.id
|
||||||
|
|
||||||
OFFSHORE_STRIKE_TARGET_UNIT_TYPE = Fortification.Oil_platform.id
|
OFFSHORE_STRIKE_TARGET_UNIT_TYPE = Fortification.Oil_platform.id
|
||||||
SHIP_UNIT_TYPE = USS_Arleigh_Burke_IIa.id
|
SHIP_UNIT_TYPE = USS_Arleigh_Burke_IIa.id
|
||||||
@ -180,6 +181,12 @@ class MizCampaignLoader:
|
|||||||
if group.units[0].type == self.INVISIBLE_FOB_UNIT_TYPE:
|
if group.units[0].type == self.INVISIBLE_FOB_UNIT_TYPE:
|
||||||
yield group
|
yield group
|
||||||
|
|
||||||
|
@property
|
||||||
|
def neutral_fobs(self) -> Iterator[VehicleGroup]:
|
||||||
|
for group in self.red.vehicle_group:
|
||||||
|
if group.units[0].type == self.NEUTRAL_FOB_UNIT_TYPE:
|
||||||
|
yield group
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ships(self) -> Iterator[ShipGroup]:
|
def ships(self) -> Iterator[ShipGroup]:
|
||||||
for group in self.red.ship_group:
|
for group in self.red.ship_group:
|
||||||
@ -345,6 +352,18 @@ class MizCampaignLoader:
|
|||||||
control_point.captured_invert = fob.late_activation
|
control_point.captured_invert = fob.late_activation
|
||||||
control_points[control_point.id] = control_point
|
control_points[control_point.id] = control_point
|
||||||
|
|
||||||
|
for fob in self.neutral_fobs:
|
||||||
|
ctld_zones = self.get_ctld_zones(fob.name)
|
||||||
|
control_point = Fob(
|
||||||
|
str(fob.name),
|
||||||
|
fob.position,
|
||||||
|
self.theater,
|
||||||
|
starts_blue=Player.NEUTRAL,
|
||||||
|
ctld_zones=ctld_zones,
|
||||||
|
)
|
||||||
|
control_point.captured_invert = fob.late_activation
|
||||||
|
control_points[control_point.id] = control_point
|
||||||
|
|
||||||
if self.cp_influence_zones:
|
if self.cp_influence_zones:
|
||||||
for cp in control_points.values():
|
for cp in control_points.values():
|
||||||
for influence_radius in self.cp_influence_zones:
|
for influence_radius in self.cp_influence_zones:
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import itertools
|
||||||
import math
|
import math
|
||||||
import operator
|
import operator
|
||||||
from collections.abc import Iterable, Iterator
|
from collections.abc import Iterable, Iterator
|
||||||
@ -278,6 +279,29 @@ class ObjectiveFinder:
|
|||||||
prioritized.extend(self._targets_by_range(isolated))
|
prioritized.extend(self._targets_by_range(isolated))
|
||||||
return prioritized
|
return prioritized
|
||||||
|
|
||||||
|
def air_assault_targets(self) -> list[ControlPoint]:
|
||||||
|
"""Returns control points suitable for air assault missions, including neutral bases."""
|
||||||
|
prioritized = []
|
||||||
|
capturable_later = []
|
||||||
|
isolated = []
|
||||||
|
|
||||||
|
combined_control_points = itertools.chain(
|
||||||
|
self.game.theater.control_points_for(self.is_player.opponent),
|
||||||
|
self.game.theater.control_points_for(Player.NEUTRAL),
|
||||||
|
)
|
||||||
|
|
||||||
|
for cp in combined_control_points:
|
||||||
|
if cp.is_isolated:
|
||||||
|
isolated.append(cp)
|
||||||
|
continue
|
||||||
|
if cp.has_active_frontline:
|
||||||
|
prioritized.append(cp)
|
||||||
|
else:
|
||||||
|
capturable_later.append(cp)
|
||||||
|
prioritized.extend(self._targets_by_range(capturable_later))
|
||||||
|
prioritized.extend(self._targets_by_range(isolated))
|
||||||
|
return prioritized
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def closest_airfields_to(location: MissionTarget) -> ClosestAirfields:
|
def closest_airfields_to(location: MissionTarget) -> ClosestAirfields:
|
||||||
"""Returns the closest airfields to the given location."""
|
"""Returns the closest airfields to the given location."""
|
||||||
|
|||||||
@ -158,6 +158,7 @@ class TheaterState(WorldState["TheaterState"]):
|
|||||||
coalition = game.coalition_for(player)
|
coalition = game.coalition_for(player)
|
||||||
finder = ObjectiveFinder(game, player)
|
finder = ObjectiveFinder(game, player)
|
||||||
ordered_capturable_points = finder.prioritized_points()
|
ordered_capturable_points = finder.prioritized_points()
|
||||||
|
air_assault_capturable_points = finder.air_assault_targets()
|
||||||
|
|
||||||
context = PersistentContext(
|
context = PersistentContext(
|
||||||
game.db,
|
game.db,
|
||||||
@ -177,7 +178,7 @@ class TheaterState(WorldState["TheaterState"]):
|
|||||||
|
|
||||||
battle_postitions: Dict[ControlPoint, BattlePositions] = {
|
battle_postitions: Dict[ControlPoint, BattlePositions] = {
|
||||||
cp: BattlePositions.for_control_point(cp)
|
cp: BattlePositions.for_control_point(cp)
|
||||||
for cp in ordered_capturable_points
|
for cp in air_assault_capturable_points
|
||||||
}
|
}
|
||||||
|
|
||||||
vulnerable_control_points = [
|
vulnerable_control_points = [
|
||||||
|
|||||||
@ -225,9 +225,9 @@ class Game:
|
|||||||
def neutral_country(self) -> Country:
|
def neutral_country(self) -> Country:
|
||||||
"""Return the best fitting country that can be used as neutral faction in the generated mission"""
|
"""Return the best fitting country that can be used as neutral faction in the generated mission"""
|
||||||
countries_in_use = {self.red.faction.country, self.blue.faction.country}
|
countries_in_use = {self.red.faction.country, self.blue.faction.country}
|
||||||
if UnitedNationsPeacekeepers not in countries_in_use:
|
if UnitedNationsPeacekeepers() not in countries_in_use:
|
||||||
return UnitedNationsPeacekeepers()
|
return UnitedNationsPeacekeepers()
|
||||||
elif Switzerland.name not in countries_in_use:
|
elif Switzerland() not in countries_in_use:
|
||||||
return Switzerland()
|
return Switzerland()
|
||||||
else:
|
else:
|
||||||
return USAFAggressors()
|
return USAFAggressors()
|
||||||
|
|||||||
@ -101,13 +101,15 @@ class LuaGenerator:
|
|||||||
for logistic_info in self.mission_data.logistics:
|
for logistic_info in self.mission_data.logistics:
|
||||||
if logistic_info.transport not in transports:
|
if logistic_info.transport not in transports:
|
||||||
transports.append(logistic_info.transport)
|
transports.append(logistic_info.transport)
|
||||||
coalition_color = "blue" if logistic_info.blue else "red"
|
coalition_color = "blue" if logistic_info.blue.is_blue else "red"
|
||||||
logistics_item = logistics_flights.add_item()
|
logistics_item = logistics_flights.add_item()
|
||||||
logistics_item.add_data_array("pilot_names", logistic_info.pilot_names)
|
logistics_item.add_data_array("pilot_names", logistic_info.pilot_names)
|
||||||
logistics_item.add_key_value("pickup_zone", logistic_info.pickup_zone)
|
logistics_item.add_key_value("pickup_zone", logistic_info.pickup_zone)
|
||||||
logistics_item.add_key_value("drop_off_zone", logistic_info.drop_off_zone)
|
logistics_item.add_key_value("drop_off_zone", logistic_info.drop_off_zone)
|
||||||
logistics_item.add_key_value("target_zone", logistic_info.target_zone)
|
logistics_item.add_key_value("target_zone", logistic_info.target_zone)
|
||||||
logistics_item.add_key_value("side", str(2 if logistic_info.blue else 1))
|
logistics_item.add_key_value(
|
||||||
|
"side", str(2 if logistic_info.blue.is_blue else 1)
|
||||||
|
)
|
||||||
logistics_item.add_key_value("logistic_unit", logistic_info.logistic_unit)
|
logistics_item.add_key_value("logistic_unit", logistic_info.logistic_unit)
|
||||||
logistics_item.add_key_value(
|
logistics_item.add_key_value(
|
||||||
"aircraft_type", logistic_info.transport.dcs_id
|
"aircraft_type", logistic_info.transport.dcs_id
|
||||||
@ -201,7 +203,9 @@ class LuaGenerator:
|
|||||||
# Should probably do the same with all the roles... but the script is already
|
# Should probably do the same with all the roles... but the script is already
|
||||||
# tolerant of those being empty.
|
# tolerant of those being empty.
|
||||||
for node in self.game.theater.iads_network.skynet_nodes(self.game):
|
for node in self.game.theater.iads_network.skynet_nodes(self.game):
|
||||||
coalition = iads_object.get_or_create_item("BLUE" if node.player else "RED")
|
coalition = iads_object.get_or_create_item(
|
||||||
|
"BLUE" if node.player.is_blue else "RED"
|
||||||
|
)
|
||||||
iads_type = coalition.get_or_create_item(node.iads_role.value)
|
iads_type = coalition.get_or_create_item(node.iads_role.value)
|
||||||
iads_element = iads_type.add_item()
|
iads_element = iads_type.add_item()
|
||||||
iads_element.add_key_value("dcsGroupName", node.dcs_name)
|
iads_element.add_key_value("dcsGroupName", node.dcs_name)
|
||||||
|
|||||||
@ -810,6 +810,9 @@ class HelipadGenerator:
|
|||||||
# capture triggers
|
# capture triggers
|
||||||
pad: BaseFARP
|
pad: BaseFARP
|
||||||
neutral_country = self.m.country(self.game.neutral_country.name)
|
neutral_country = self.m.country(self.game.neutral_country.name)
|
||||||
|
if self.cp.captured is Player.NEUTRAL:
|
||||||
|
country = neutral_country
|
||||||
|
else:
|
||||||
country = self.m.country(
|
country = self.m.country(
|
||||||
self.game.coalition_for(self.cp.captured).faction.country.name
|
self.game.coalition_for(self.cp.captured).faction.country.name
|
||||||
)
|
)
|
||||||
@ -1403,6 +1406,10 @@ class TgoGenerator:
|
|||||||
|
|
||||||
def generate(self) -> None:
|
def generate(self) -> None:
|
||||||
for cp in self.game.theater.controlpoints:
|
for cp in self.game.theater.controlpoints:
|
||||||
|
# Use neutral country for neutral control points
|
||||||
|
if cp.captured is Player.NEUTRAL:
|
||||||
|
country = self.m.country(self.game.neutral_country.name)
|
||||||
|
else:
|
||||||
country = self.m.country(cp.coalition.faction.country.name)
|
country = self.m.country(cp.coalition.faction.country.name)
|
||||||
|
|
||||||
# Generate helipads
|
# Generate helipads
|
||||||
|
|||||||
@ -305,12 +305,12 @@ class QGroundObjectMenu(QDialog):
|
|||||||
self.game.theater.iads_network.update_tgo(self.ground_object, events)
|
self.game.theater.iads_network.update_tgo(self.ground_object, events)
|
||||||
if any(
|
if any(
|
||||||
package.target == self.ground_object
|
package.target == self.ground_object
|
||||||
for package in self.game.ato_for(player=False).packages
|
for package in self.game.ato_for(player=Player.RED).packages
|
||||||
):
|
):
|
||||||
# Replan if the tgo was a target of the redfor
|
# Replan if the tgo was a target of the redfor
|
||||||
coalition = self.ground_object.coalition
|
coalition = self.ground_object.coalition
|
||||||
self.game.initialize_turn(
|
self.game.initialize_turn(
|
||||||
events, for_red=coalition.player, for_blue=not coalition.player
|
events, for_red=coalition.player, for_blue=coalition.player.opponent
|
||||||
)
|
)
|
||||||
EventStream.put_nowait(events)
|
EventStream.put_nowait(events)
|
||||||
GameUpdateSignal.get_instance().updateGame(self.game)
|
GameUpdateSignal.get_instance().updateGame(self.game)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user