GroundForcePainter for applying custom liveries to ground units and ships (#26)

See #26 for more info
This commit is contained in:
MetalStormGhost 2022-12-03 17:11:22 +02:00 committed by GitHub
parent 0c30ce3bb3
commit f5c7935993
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 123 additions and 3 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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: