Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/Chilli935/dcs-retribution in…
Browse files Browse the repository at this point in the history
…to dev
  • Loading branch information
Chilli935 committed Jun 24, 2024
2 parents 6bf908c + 45edc7a commit 1acfc34
Show file tree
Hide file tree
Showing 269 changed files with 8,059 additions and 1,821 deletions.
4 changes: 2 additions & 2 deletions .github/actions/build-app/action.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Build Liberation package
description: Assembles the full Liberation application.
name: Build Retribution package
description: Assembles the full Retribution application.
runs:
using: composite
steps:
Expand Down
4 changes: 2 additions & 2 deletions .github/actions/setup-liberation-js/action.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Liberation JS set-up
description: Sets up the Liberation Javascript environment.
name: Retribution JS set-up
description: Sets up the Retribution Javascript environment.
runs:
using: composite
steps:
Expand Down
6 changes: 3 additions & 3 deletions .github/actions/setup-liberation-python/action.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: Liberation Python set-up
description: Sets up the Liberation Python environment.
name: Retribution Python set-up
description: Sets up the Retribution Python environment.
runs:
using: composite
steps:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.10"
python-version: "3.11"
cache: pip

- name: Install environment
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
include_image: true
avatar_url: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
username: GitHub Build Notifier
if: startsWith(github.ref_name, 'test')
if: github.repository == 'dcs-retribution/dcs-retribution' && startsWith(github.ref_name, 'test')

- name: Send status to Discord
uses: stegzilla/discord-notify@v2
Expand All @@ -60,4 +60,4 @@ jobs:
include_image: true
avatar_url: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
username: GitHub Build Notifier
if: github.ref_name == 'dev'
if: github.repository == 'dcs-retribution/dcs-retribution' && github.ref_name == 'dev'
18 changes: 16 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,24 @@
* **[Factions]** Support for definitions in yml/yaml format
* **[Campaigns/Factions]** Support for inline recommended faction in campaign's yaml file
* **[Squadrons]** Ability to define a livery-set for each squadron from which Retribution will randomly choose during mission generation
* **[Modding]** Updated support for F/A-18E/F/G mod version 2.2.5
* **[Modding]** Added VSN F-106 Delta Dart mod support (v2.9.4.101)
* **[Campaign Setup]** Allow adjustments to naval TGOs (except carriers) on turn 0
* **[Campaign Design]** Ability to configure specific carrier names & types in campaign's yaml file
* **[Mission Generation]** Ability to inject custom kneeboards
* **[Options]** Extend option (so it can be disabled when fixed in DCS) to force air-starts (except for the slots that work) at Ramon Airbase, similar to the Nevatim fix in Retribution 1.3.0
* **[Options]** New option in Settings: Default start type for Player flights.
* **[AirWing]** Expose OPFOR Squadrons, giving the ability to change liveries, auto-assignable mission types & an easy way to retrieve debug information.
* **[ATO]** Allow planning as OPFOR
* **[Campaign Design]** Support for Kola map by Orbx
* **[UI]** Zoom level retained when switching campaigns
* **[UX]** Allow changing squadrons in flight's edit dialog

## Fixes
* **[UI/UX]** A-10A flights can be edited again.

* **[UI/UX]** A-10A flights can be edited again
* **[Mission Generation]** IADS bug sometimes triggering "no skynet usable units" error during mission generation
* **[New Game Wizard]** Campaign errors show a dialog again and avoid CTDs
* **[UI]** Landmap wasn't updating when switching to a different theater

# Retribution v1.3.1
#### Note: Re-save your missions in DCS' Mission Editor to avoid possible crashes due to datalink (usually the case when F-16C blk50s are used) when hosting missions on a dedicated server.
Expand Down
12 changes: 6 additions & 6 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/src/api/_liberationApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ export type Game = {
navmeshes: NavMeshes;
map_center?: LatLng;
unculled_zones: UnculledZone[];
map_zones: MapZones;
};
export type MapZones = {
inclusion: LatLng[][][];
Expand Down
34 changes: 34 additions & 0 deletions client/src/api/mapZonesSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { RootState } from "../app/store";
import { gameLoaded, gameUnloaded } from "./actions";
import { createSlice } from "@reduxjs/toolkit";
import { MapZones } from "./_liberationApi";

interface MapZonesState {
mapZones: MapZones;
}

const initialState: MapZonesState = {
mapZones: { inclusion: [], exclusion: [], sea: [] },
};

const mapZonesSlice = createSlice({
name: "map",
initialState: initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(gameLoaded, (state, action) => {
if (action.payload != null) {
state.mapZones.exclusion = action.payload.map_zones.exclusion;
state.mapZones.inclusion = action.payload.map_zones.inclusion;
state.mapZones.sea = action.payload.map_zones.sea;
}
});
builder.addCase(gameUnloaded, (state) => {
state.mapZones = initialState.mapZones;
});
},
});

export const selectMapZones = (state: RootState) => state.mapZones;

export default mapZonesSlice.reducer;
2 changes: 2 additions & 0 deletions client/src/app/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import supplyRoutesReducer from "../api/supplyRoutesSlice";
import tgosReducer from "../api/tgosSlice";
import threatZonesReducer from "../api/threatZonesSlice";
import unculledZonesReducer from "../api/unculledZonesSlice";
import mapZonesReducer from "../api/mapZonesSlice";
import {
Action,
PreloadedState,
Expand All @@ -31,6 +32,7 @@ const rootReducer = combineReducers({
threatZones: threatZonesReducer,
[baseApi.reducerPath]: baseApi.reducer,
unculledZones: unculledZonesReducer,
mapZones: mapZonesReducer,
});

export function setupStore(preloadedState?: PreloadedState<RootState>) {
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/liberationmap/LiberationMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ export default function LiberationMap() {
const map = useRef<Map>(null);
const mapCenter = useAppSelector(selectMapCenter);
useEffect(() => {
map.current?.setView(mapCenter, 8, { animate: true, duration: 1 });
map.current?.setView(mapCenter, map.current?.getZoom() ?? 8, { animate: true, duration: 1 });
});
return (
<MapContainer zoom={8} zoomControl={false} ref={map}>
<MapContainer zoom={map.current?.getZoom() ?? 8} zoomControl={false} ref={map}>
<ScaleControl />
<LeafletRuler />
<LayersControl collapsed={false}>
Expand Down
18 changes: 7 additions & 11 deletions client/src/components/terrainzones/TerrainZonesLayers.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useGetTerrainZonesQuery } from "../../api/liberationApi";
import { useAppSelector } from "../../app/hooks";
import { LatLngLiteral } from "leaflet";
import { LayerGroup, LayersControl, Polygon } from "react-leaflet";
import { selectMapZones } from "../../api/mapZonesSlice";

interface TerrainZoneLayerProps {
zones: LatLngLiteral[][][];
Expand Down Expand Up @@ -28,33 +29,28 @@ function TerrainZoneLayer(props: TerrainZoneLayerProps) {
}

export default function TerrainZonesLayers() {
const { data, error, isLoading } = useGetTerrainZonesQuery();
const zones = useAppSelector(selectMapZones).mapZones;
var exclusion = <></>;
var inclusion = <></>;
var sea = <></>;

if (error) {
console.error("Error while loading terrain zones", error);
} else if (isLoading) {
} else if (!data) {
console.log("Empty response when loading terrain zones");
} else {
if (zones) {
exclusion = (
<TerrainZoneLayer
zones={data.exclusion}
zones={zones.exclusion}
color="#969696"
fillColor="#303030"
/>
);
inclusion = (
<TerrainZoneLayer
zones={data.inclusion}
zones={zones.inclusion}
color="#969696"
fillColor="#4b4b4b"
/>
);
sea = (
<TerrainZoneLayer zones={data.sea} color="#344455" fillColor="#344455" />
<TerrainZoneLayer zones={zones.sea} color="#344455" fillColor="#344455" />
);
}
return (
Expand Down
18 changes: 13 additions & 5 deletions game/ato/flightplans/airassault.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,18 @@ def layout(self) -> AirAssaultLayout:
pickup.alt = altitude
pickup_position = pickup.position

ingress = builder.ingress(
FlightWaypointType.INGRESS_AIR_ASSAULT,
self.package.waypoints.ingress,
self.package.target,
ingress = (
builder.ingress(
FlightWaypointType.INGRESS_AIR_ASSAULT,
self.package.waypoints.ingress,
self.package.target,
)
if not self.flight.is_hercules
else builder.ingress(
FlightWaypointType.INGRESS_AIR_ASSAULT,
self.package.waypoints.initial,
self.package.target,
)
)

assault_area = builder.assault_area(self.package.target)
Expand Down Expand Up @@ -182,7 +190,7 @@ def layout(self) -> AirAssaultLayout:
divert=builder.divert(self.flight.divert),
bullseye=builder.bullseye(),
hold=None,
join=builder.join(ingress.position),
join=builder.join(self.package.waypoints.ingress),
split=builder.split(self.flight.arrival.position),
refuel=None,
custom_waypoints=list(),
Expand Down
4 changes: 4 additions & 0 deletions game/ato/flightroster.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def squadron(self) -> Squadron:
def iter_pilots(self) -> Iterator[Pilot | None]:
yield from self.pilots

@property
def player_count(self) -> int:
return len([p for p in self.pilots if p is not None and p.player])

def pilot_at(self, idx: int) -> Pilot | None:
return self.pilots[idx]

Expand Down
17 changes: 16 additions & 1 deletion game/ato/flightwaypoint.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from __future__ import annotations

from copy import deepcopy
from dataclasses import dataclass, field
from datetime import datetime
from typing import Literal, TYPE_CHECKING
from typing import Literal, TYPE_CHECKING, Any, Dict, Optional

from dcs import Point

Expand Down Expand Up @@ -56,3 +57,17 @@ def y(self) -> float:

def __hash__(self) -> int:
return hash(id(self))

def __deepcopy__(self, memo: Optional[Dict[int, Any]] = None) -> FlightWaypoint:
obj = FlightWaypoint(self.name, self.waypoint_type, self.position)
for attr in dir(self):
if attr == "control_point":
obj.control_point = self.control_point
elif attr == "targets":
obj.targets = self.targets
elif "__" in attr or attr not in obj.__dataclass_fields__:
continue
else:
attr_copy = deepcopy(getattr(self, attr))
setattr(obj, attr, attr_copy)
return obj
5 changes: 5 additions & 0 deletions game/ato/iflightroster.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ def squadron(self) -> Squadron:
def max_size(self) -> int:
...

@property
@abstractmethod
def player_count(self) -> int:
...

@abstractmethod
def resize(self, new_size: int) -> None:
...
Expand Down
1 change: 1 addition & 0 deletions game/ato/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ def clone_package(package: Package) -> Package:
clone.time_over_target = deepcopy(package.time_over_target)
for f in package.flights:
cf = Flight.clone_flight(f)
cf.flight_plan.layout = deepcopy(f.flight_plan.layout)
cf.package = clone
clone.add_flight(cf)
return clone
8 changes: 8 additions & 0 deletions game/campaignloader/campaign.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from game.theater.theaterloader import TheaterLoader
from game.version import CAMPAIGN_FORMAT_VERSION
from .campaignairwingconfig import CampaignAirWingConfig
from .campaigncarrierconfig import CampaignCarrierConfig
from .campaigngroundconfig import TgoConfig
from .mizcampaignloader import MizCampaignLoader
from ..factions import FACTIONS, Faction
Expand Down Expand Up @@ -164,6 +165,13 @@ def load_air_wing_config(self, theater: ConflictTheater) -> CampaignAirWingConfi
return CampaignAirWingConfig({})
return CampaignAirWingConfig.from_campaign_data(squadron_data, theater)

def load_carrier_config(self) -> CampaignCarrierConfig:
try:
carrier_data = self.data["carriers"]
except KeyError:
return CampaignCarrierConfig({})
return CampaignCarrierConfig.from_campaign_data(carrier_data)

def load_ground_forces_config(self) -> TgoConfig:
ground_forces = self.data.get("ground_forces", {})
if not ground_forces:
Expand Down
42 changes: 42 additions & 0 deletions game/campaignloader/campaigncarrierconfig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from __future__ import annotations

import logging
from collections import defaultdict
from dataclasses import dataclass
from typing import Any, TYPE_CHECKING

from game.dcs.shipunittype import ShipUnitType

if TYPE_CHECKING:
pass


@dataclass(frozen=True)
class CarrierConfig:
preferred_name: str
preferred_type: ShipUnitType

@classmethod
def from_data(cls, data: dict[str, Any]) -> CarrierConfig:
return CarrierConfig(
str(data["preferred_name"]), ShipUnitType.named(data["preferred_type"])
)


@dataclass(frozen=True)
class CampaignCarrierConfig:
by_original_name: dict[str, CarrierConfig]

@classmethod
def from_campaign_data(cls, data: dict[str, Any]) -> CampaignCarrierConfig:
by_original_name: dict[str, CarrierConfig] = defaultdict()
for original_name, carrier_config_data in data.items():
try:
carrier_config = CarrierConfig.from_data(carrier_config_data)
by_original_name[original_name] = carrier_config
except KeyError:
logging.warning(
f"Skipping invalid carrier config for '{original_name}'"
)

return CampaignCarrierConfig(by_original_name)
Loading

0 comments on commit 1acfc34

Please sign in to comment.