mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
GroundForcePainter for applying custom liveries to ground units and ships (#26)
See #26 for more info
This commit is contained in:
parent
0c30ce3bb3
commit
f5c7935993
@ -4,6 +4,7 @@
|
||||
* **[Engine]** Support for DCS v2.8.0.32066.
|
||||
* **[Briefing]** Add tanker info to mission briefing
|
||||
* **[Campaign]** Add 3 new campaigns by Oscar Juliet from WRL
|
||||
* **[Campaign]** Add ability to define livery overrides also for ground/naval units
|
||||
* **[Data]** Added data to support C-47 Skytrain.
|
||||
* **[Data]** Added data to support KS-19 & SON-9, including support for "AAA Site" layout.
|
||||
* **[Mission Generation]** Add option to configure the maximum front-line length in settings
|
||||
|
||||
@ -116,6 +116,9 @@ class Faction:
|
||||
# List of default livery overrides
|
||||
liveries_overrides: Dict[AircraftType, List[str]] = field(default_factory=dict)
|
||||
|
||||
# List of default livery overrides for ground vehicles
|
||||
liveries_overrides_ground_forces: Dict[str, List[str]] = field(default_factory=dict)
|
||||
|
||||
#: Set to True if the faction should force the "Unrestricted satnav" option
|
||||
#: for the mission. This option enables GPS for capable aircraft regardless
|
||||
#: of the time period or operator. For example, the CJTF "countries" don't
|
||||
@ -284,6 +287,16 @@ class Faction:
|
||||
aircraft = AircraftType.named(name)
|
||||
faction.liveries_overrides[aircraft] = [s.lower() for s in livery]
|
||||
|
||||
# Load liveries override for ground forces
|
||||
faction.liveries_overrides_ground_forces = {}
|
||||
liveries_overrides_ground_forces = json.get(
|
||||
"liveries_overrides_ground_forces", {}
|
||||
)
|
||||
for vehicle_type, livery in liveries_overrides_ground_forces.items():
|
||||
faction.liveries_overrides_ground_forces[vehicle_type] = [
|
||||
s.lower() for s in livery
|
||||
]
|
||||
|
||||
faction.unrestricted_satnav = json.get("unrestricted_satnav", False)
|
||||
|
||||
return faction
|
||||
|
||||
@ -10,6 +10,7 @@ from dcs.unit import Vehicle
|
||||
from dcs.unitgroup import VehicleGroup
|
||||
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
from game.missiongenerator.groundforcepainter import GroundForcePainter
|
||||
from game.transfers import Convoy
|
||||
from game.unitmap import UnitMap
|
||||
from game.utils import kph
|
||||
@ -72,6 +73,7 @@ class ConvoyGenerator:
|
||||
for_player: bool,
|
||||
) -> VehicleGroup:
|
||||
country = self.mission.country(self.game.coalition_for(for_player).country_name)
|
||||
faction = self.game.faction_for(for_player)
|
||||
|
||||
unit_types = list(units.items())
|
||||
main_unit_type, main_unit_count = unit_types[0]
|
||||
@ -97,6 +99,7 @@ class ConvoyGenerator:
|
||||
v.position.x = position.x
|
||||
v.position.y = next(y)
|
||||
v.heading = 0
|
||||
GroundForcePainter(faction, v).apply_livery()
|
||||
group.add_unit(v)
|
||||
|
||||
return group
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import math
|
||||
import random
|
||||
from typing import List, Optional, TYPE_CHECKING, Tuple
|
||||
@ -43,6 +44,7 @@ from game.theater.controlpoint import ControlPoint
|
||||
from game.unitmap import UnitMap
|
||||
from game.utils import Heading
|
||||
from .frontlineconflictdescription import FrontLineConflictDescription
|
||||
from .groundforcepainter import GroundForcePainter
|
||||
from .lasercoderegistry import LaserCodeRegistry
|
||||
from .missiondata import JtacInfo, MissionData
|
||||
|
||||
@ -221,7 +223,7 @@ class FlotGenerator:
|
||||
u = random.choices(
|
||||
manpads, weights=[m.spawn_weight for m in manpads]
|
||||
)[0]
|
||||
self.mission.vehicle_group(
|
||||
vg = self.mission.vehicle_group(
|
||||
side,
|
||||
namegen.next_infantry_name(side, u),
|
||||
u.dcs_unit_type,
|
||||
@ -230,6 +232,8 @@ class FlotGenerator:
|
||||
heading=forward_heading.degrees,
|
||||
move_formation=PointAction.OffRoad,
|
||||
)
|
||||
vehicle = vg.units[0]
|
||||
GroundForcePainter(faction, vehicle).apply_livery()
|
||||
return
|
||||
|
||||
possible_infantry_units = set(faction.infantry_with_class(UnitClass.INFANTRY))
|
||||
@ -246,7 +250,7 @@ class FlotGenerator:
|
||||
weights=[u.spawn_weight for u in infantry_choices],
|
||||
k=INFANTRY_GROUP_SIZE,
|
||||
)
|
||||
self.mission.vehicle_group(
|
||||
vg = self.mission.vehicle_group(
|
||||
side,
|
||||
namegen.next_infantry_name(side, units[0]),
|
||||
units[0].dcs_unit_type,
|
||||
@ -255,10 +259,12 @@ class FlotGenerator:
|
||||
heading=forward_heading.degrees,
|
||||
move_formation=PointAction.OffRoad,
|
||||
)
|
||||
vehicle = vg.units[0]
|
||||
GroundForcePainter(faction, vehicle).apply_livery()
|
||||
|
||||
for unit in units[1:]:
|
||||
position = infantry_position.random_point_within(55, 5)
|
||||
self.mission.vehicle_group(
|
||||
vg = self.mission.vehicle_group(
|
||||
side,
|
||||
namegen.next_infantry_name(side, unit),
|
||||
unit.dcs_unit_type,
|
||||
@ -267,6 +273,8 @@ class FlotGenerator:
|
||||
heading=forward_heading.degrees,
|
||||
move_formation=PointAction.OffRoad,
|
||||
)
|
||||
vehicle = vg.units[0]
|
||||
GroundForcePainter(faction, vehicle).apply_livery()
|
||||
|
||||
def _set_reform_waypoint(
|
||||
self, dcs_group: VehicleGroup, forward_heading: Heading
|
||||
@ -769,6 +777,8 @@ class FlotGenerator:
|
||||
heading: Heading,
|
||||
) -> VehicleGroup:
|
||||
cp = self.conflict.front_line.control_point_friendly_to(player)
|
||||
faction = self.game.faction_for(player)
|
||||
|
||||
group = self.mission.vehicle_group(
|
||||
side,
|
||||
namegen.next_unit_name(side, unit_type),
|
||||
@ -783,5 +793,6 @@ class FlotGenerator:
|
||||
for c in range(count):
|
||||
vehicle: Vehicle = group.units[c]
|
||||
vehicle.player_can_drive = True
|
||||
GroundForcePainter(faction, vehicle).apply_livery()
|
||||
|
||||
return group
|
||||
|
||||
82
game/missiongenerator/groundforcepainter.py
Normal file
82
game/missiongenerator/groundforcepainter.py
Normal file
@ -0,0 +1,82 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import random
|
||||
from typing import Any, Optional
|
||||
|
||||
from dcs.unit import Ship
|
||||
from dcs.unitgroup import Vehicle
|
||||
|
||||
from game.factions.faction import Faction
|
||||
|
||||
|
||||
class GroundForcePainter:
|
||||
def __init__(self, faction: Faction, vehicle: Vehicle) -> None:
|
||||
self.faction = faction
|
||||
self.vehicle = vehicle
|
||||
|
||||
def livery_from_faction(self) -> Optional[str]:
|
||||
faction = self.faction
|
||||
try:
|
||||
if (
|
||||
choices := faction.liveries_overrides_ground_forces.get(
|
||||
self.vehicle.type
|
||||
)
|
||||
) is not None:
|
||||
return random.choice(choices)
|
||||
except AttributeError:
|
||||
logging.warning(
|
||||
f"Faction {self.faction.name} is missing livery for ground unit {self.vehicle.type}"
|
||||
)
|
||||
return None
|
||||
logging.warning(
|
||||
f"Faction {self.faction.name} is missing livery for ground unit {self.vehicle.type}"
|
||||
)
|
||||
return None
|
||||
|
||||
def determine_livery(self) -> Optional[str]:
|
||||
if (livery := self.livery_from_faction()) is not None:
|
||||
return livery
|
||||
return None
|
||||
|
||||
def apply_livery(self) -> None:
|
||||
livery = self.determine_livery()
|
||||
if livery is None:
|
||||
return
|
||||
self.vehicle.livery_id = livery
|
||||
|
||||
|
||||
class NavalForcePainter:
|
||||
def __init__(self, faction: Faction, vessel: Ship) -> None:
|
||||
self.faction = faction
|
||||
self.vessel = vessel
|
||||
|
||||
def livery_from_faction(self) -> Optional[str]:
|
||||
faction = self.faction
|
||||
try:
|
||||
if (
|
||||
choices := faction.liveries_overrides_ground_forces.get(
|
||||
self.vessel.type
|
||||
)
|
||||
) is not None:
|
||||
return random.choice(choices)
|
||||
except AttributeError:
|
||||
logging.warning(
|
||||
f"Faction {self.faction.name} is missing livery for naval unit {self.vessel.type}"
|
||||
)
|
||||
return None
|
||||
logging.warning(
|
||||
f"Faction {self.faction.name} is missing livery for naval unit {self.vessel.type}"
|
||||
)
|
||||
return None
|
||||
|
||||
def determine_livery(self) -> Optional[str]:
|
||||
if (livery := self.livery_from_faction()) is not None:
|
||||
return livery
|
||||
return None
|
||||
|
||||
def apply_livery(self) -> None:
|
||||
livery = self.determine_livery()
|
||||
if livery is None:
|
||||
return
|
||||
self.vessel.livery_id = livery
|
||||
@ -40,6 +40,10 @@ from dcs.unitgroup import MovingGroup, ShipGroup, StaticGroup, VehicleGroup
|
||||
from dcs.unittype import ShipType, VehicleType
|
||||
from dcs.vehicles import vehicle_map
|
||||
|
||||
from game.missiongenerator.groundforcepainter import (
|
||||
NavalForcePainter,
|
||||
GroundForcePainter,
|
||||
)
|
||||
from game.missiongenerator.missiondata import CarrierInfo, MissionData
|
||||
from game.radio.radios import RadioFrequency, RadioRegistry
|
||||
from game.radio.tacan import TacanBand, TacanChannel, TacanRegistry, TacanUsage
|
||||
@ -122,6 +126,7 @@ class GroundObjectGenerator:
|
||||
vehicle_group: Optional[VehicleGroup] = None
|
||||
for unit in units:
|
||||
assert issubclass(unit.type, VehicleType)
|
||||
faction = unit.ground_object.control_point.coalition.faction
|
||||
if vehicle_group is None:
|
||||
vehicle_group = self.m.vehicle_group(
|
||||
self.country,
|
||||
@ -134,11 +139,13 @@ class GroundObjectGenerator:
|
||||
self.enable_eplrs(vehicle_group, unit.type)
|
||||
vehicle_group.units[0].name = unit.unit_name
|
||||
self.set_alarm_state(vehicle_group)
|
||||
GroundForcePainter(faction, vehicle_group.units[0]).apply_livery()
|
||||
else:
|
||||
vehicle_unit = self.m.vehicle(unit.unit_name, unit.type)
|
||||
vehicle_unit.player_can_drive = True
|
||||
vehicle_unit.position = unit.position
|
||||
vehicle_unit.heading = unit.position.heading.degrees
|
||||
GroundForcePainter(faction, vehicle_unit).apply_livery()
|
||||
vehicle_group.add_unit(vehicle_unit)
|
||||
self._register_theater_unit(unit, vehicle_group.units[-1])
|
||||
if vehicle_group is None:
|
||||
@ -154,6 +161,7 @@ class GroundObjectGenerator:
|
||||
ship_group: Optional[ShipGroup] = None
|
||||
for unit in units:
|
||||
assert issubclass(unit.type, ShipType)
|
||||
faction = unit.ground_object.control_point.coalition.faction
|
||||
if ship_group is None:
|
||||
ship_group = self.m.ship_group(
|
||||
self.country,
|
||||
@ -166,12 +174,14 @@ class GroundObjectGenerator:
|
||||
ship_group.set_frequency(frequency.hertz)
|
||||
ship_group.units[0].name = unit.unit_name
|
||||
self.set_alarm_state(ship_group)
|
||||
NavalForcePainter(faction, ship_group.units[0]).apply_livery()
|
||||
else:
|
||||
ship_unit = self.m.ship(unit.unit_name, unit.type)
|
||||
if frequency:
|
||||
ship_unit.set_frequency(frequency.hertz)
|
||||
ship_unit.position = unit.position
|
||||
ship_unit.heading = unit.position.heading.degrees
|
||||
NavalForcePainter(faction, ship_unit).apply_livery()
|
||||
ship_group.add_unit(ship_unit)
|
||||
self._register_theater_unit(unit, ship_group.units[-1])
|
||||
if ship_group is None:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user