Implement advanced skynet functions

- factor out own class for the iadsnetwork within the conflicttheater
- This class will handle all Skynet related things - no specific group_name handling necessary in future
- make iadsbuilding own TGO class because SAM & EWRs are Vehicle Groups. IADS Elements dont have any groups attached.
- added command center, connection node and power source as Ground objects which can be added by the campaign designer
- adjust lua generator to support new iads units
- parse the campaign yaml to get the iads network information
- use the range as fallback if no yaml information was found
- complete rewrite of the skynet lua script
- allow destruction of iads network to be persistent over all rounds
- modified the presetlocation handling: the wrapper PresetLocation for PointWithHeading now stores the original name from the campaign miz to have the ability to process campaign yaml configurations based on the ground unit
- Implementation of the UI representation for the IADS Network
- Give user the option to enable or disable advanced iads
- Extended the layout system: Implement Sub task handling to support PD
This commit is contained in:
RndName
2021-07-04 10:23:12 +02:00
parent 138e48dc2d
commit 5cdfe62e2d
53 changed files with 1099 additions and 428 deletions

View File

@@ -198,6 +198,18 @@ const injectedRtkApi = api.injectEndpoints({
body: queryArg.leafletPoint,
}),
}),
getIadsNetwork: build.query<
GetIadsNetworkApiResponse,
GetIadsNetworkApiArg
>({
query: () => ({ url: `/iads-network/` }),
}),
getIadsConnectionsForTgo: build.query<
GetIadsConnectionsForTgoApiResponse,
GetIadsConnectionsForTgoApiArg
>({
query: (queryArg) => ({ url: `/iads-network/for-tgo/${queryArg.tgoId}` }),
}),
}),
overrideExisting: false,
});
@@ -330,6 +342,14 @@ export type SetWaypointPositionApiArg = {
waypointIdx: number;
leafletPoint: LatLng;
};
export type GetIadsNetworkApiResponse =
/** status 200 Successful Response */ IadsNetwork;
export type GetIadsNetworkApiArg = void;
export type GetIadsConnectionsForTgoApiResponse =
/** status 200 Successful Response */ IadsConnection[];
export type GetIadsConnectionsForTgoApiArg = {
tgoId: string;
};
export type LatLng = {
lat: number;
lng: number;
@@ -414,6 +434,19 @@ export type SupplyRoute = {
blue: boolean;
active_transports: string[];
};
export type IadsConnection = {
id: string;
points: LatLng[];
node: string;
connected: string;
active: boolean;
blue: boolean;
is_power: boolean;
};
export type IadsNetwork = {
advanced: boolean;
connections: IadsConnection[];
};
export type ThreatZones = {
full: LatLng[][];
aircraft: LatLng[][];
@@ -441,6 +474,7 @@ export type Game = {
supply_routes: SupplyRoute[];
front_lines: FrontLine[];
flights: Flight[];
iads_network: IadsNetwork;
threat_zones: ThreatZoneContainer;
navmeshes: NavMeshes;
map_center?: LatLng;
@@ -483,4 +517,6 @@ export const {
useGetTgoByIdQuery,
useListAllWaypointsForFlightQuery,
useSetWaypointPositionMutation,
useGetIadsNetworkQuery,
useGetIadsConnectionsForTgoQuery,
} = injectedRtkApi;

View File

@@ -29,6 +29,8 @@ import { navMeshUpdated } from "./navMeshSlice";
import { updateTgo } from "./tgosSlice";
import { threatZonesUpdated } from "./threatZonesSlice";
import { LatLng } from "leaflet";
import { updateIadsConnection } from "./iadsNetworkSlice";
import { IadsConnection } from "./_liberationApi";
interface GameUpdateEvents {
updated_flight_positions: { [id: string]: LatLng };
@@ -138,6 +140,11 @@ export const handleStreamedEvents = (
const tgo = response.data as Tgo;
dispatch(updateTgo(tgo));
});
backend.get(`/iads-network/for-tgo/${id}`).then((response) => {
for (const connection of response.data) {
dispatch(updateIadsConnection(connection as IadsConnection));
}
});
}
for (const id of events.updated_control_points) {

View File

@@ -0,0 +1,43 @@
import { RootState } from "../app/store";
import { gameLoaded, gameUnloaded } from "./actions";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { IadsConnection} from "./_liberationApi";
interface IadsNetworkState {
connections: {[key: string]: IadsConnection}
}
const initialState: IadsNetworkState = {
connections: {},
};
export const IadsNetworkSlice = createSlice({
name: "iadsNetwork",
initialState,
reducers: {
updateIadsConnection: (state, action: PayloadAction<IadsConnection>) => {
const connection = action.payload;
state.connections[connection.id] = connection
},
},
extraReducers: (builder) => {
builder.addCase(gameLoaded, (state, action) => {
state.connections = action.payload.iads_network.connections.reduce(
(acc: { [key: string]: IadsConnection }, curr) => {
acc[curr.id] = curr;
return acc;
},
{}
);
});
builder.addCase(gameUnloaded, (state) => {
state.connections = {};
});
},
});
export const { updateIadsConnection } = IadsNetworkSlice.actions;
export const selectIadsNetwork = (state: RootState) => state.iadsNetwork;
export default IadsNetworkSlice.reducer;

View File

@@ -7,6 +7,7 @@ import mapReducer from "../api/mapSlice";
import navMeshReducer from "../api/navMeshSlice";
import supplyRoutesReducer from "../api/supplyRoutesSlice";
import tgosReducer from "../api/tgosSlice";
import iadsNetworkReducer from "../api/iadsNetworkSlice";
import threatZonesReducer from "../api/threatZonesSlice";
import { Action, ThunkAction, configureStore } from "@reduxjs/toolkit";
@@ -19,6 +20,7 @@ export const store = configureStore({
map: mapReducer,
navmeshes: navMeshReducer,
supplyRoutes: supplyRoutesReducer,
iadsNetwork: iadsNetworkReducer,
tgos: tgosReducer,
threatZones: threatZonesReducer,
[baseApi.reducerPath]: baseApi.reducer,

View File

@@ -0,0 +1,39 @@
import { IadsConnection as IadsConnectionModel } from "../../api/liberationApi";
import { Polyline as LPolyline } from "leaflet";
import { useRef } from "react";
import { Polyline, Tooltip } from "react-leaflet";
interface IadsConnectionProps {
iads_connection: IadsConnectionModel;
}
function IadsConnectionTooltip(props: IadsConnectionProps) {
var status = props.iads_connection.active ? "Active" : "Inactive";
if (props.iads_connection.is_power) {
return <Tooltip>Power Connection ({status})</Tooltip>;
} else {
return <Tooltip>Communication Connection ({status})</Tooltip>;
}
}
export default function IadsConnection(props: IadsConnectionProps) {
const color = props.iads_connection.is_power ? "#FFD580" : "#87CEEB";
const path = useRef<LPolyline | null>();
const weight = 1
var opacity = props.iads_connection.active ? 1.0 : 0.5
var dashArray = props.iads_connection.active ? "" : "20"
return (
<Polyline
positions={props.iads_connection.points}
color={color}
weight={weight}
opacity={opacity}
dashArray={dashArray}
ref={(ref) => (path.current = ref)}
>
<IadsConnectionTooltip {...props} />
</Polyline>
);
}

View File

@@ -0,0 +1 @@
export { default } from "./IadsNetwork";

View File

@@ -0,0 +1,26 @@
import { useAppSelector } from "../../app/hooks";
import { LayerGroup } from "react-leaflet";
import IadsConnection from "../iadsnetwork/IadsNetwork";
import { selectIadsNetwork } from "../../api/iadsNetworkSlice";
interface IadsNetworkLayerProps {
blue: boolean;
}
export const IadsNetworkLayer = (props: IadsNetworkLayerProps) => {
const connections = Object.values(useAppSelector(selectIadsNetwork).connections);
var iadsConnectionsForSide = connections.filter((connection) => connection.blue === props.blue);
return (
<LayerGroup>
{iadsConnectionsForSide.map((connection) => {
return (
<IadsConnection key={connection.id} iads_connection={connection} />
);
})}
</LayerGroup>
);
};
export default IadsNetworkLayer;

View File

@@ -0,0 +1 @@
export { default } from "./IadsNetworkLayer";

View File

@@ -17,6 +17,7 @@ import { Map } from "leaflet";
import { useEffect, useRef } from "react";
import { BasemapLayer } from "react-esri-leaflet";
import { LayersControl, MapContainer, ScaleControl } from "react-leaflet";
import Iadsnetworklayer from "../iadsnetworklayer";
export default function LiberationMap() {
const map = useRef<Map>();
@@ -74,12 +75,18 @@ export default function LiberationMap() {
<LayersControl.Overlay name="Enemy SAM detection range">
<AirDefenseRangeLayer blue={false} detection />
</LayersControl.Overlay>
<LayersControl.Overlay name="Enemy IADS Network">
<Iadsnetworklayer blue={false} />
</LayersControl.Overlay>
<LayersControl.Overlay name="Allied SAM threat range">
<AirDefenseRangeLayer blue={true} />
</LayersControl.Overlay>
<LayersControl.Overlay name="Allied SAM detection range">
<AirDefenseRangeLayer blue={true} detection />
</LayersControl.Overlay>
<LayersControl.Overlay name="Allied IADS Network">
<Iadsnetworklayer blue={true} />
</LayersControl.Overlay>
<LayersControl.Overlay name="Selected blue flight plan">
<FlightPlansLayer blue={true} selectedOnly />
</LayersControl.Overlay>