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