mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
More work adding back missing functions
This commit is contained in:
@@ -5,6 +5,7 @@ import { UnitBlueprint } from "../../interfaces";
|
||||
import { faArrowRight } from "@fortawesome/free-solid-svg-icons/faArrowRight";
|
||||
|
||||
export function OlUnitListEntry(props: { icon: IconProp; blueprint: UnitBlueprint; onClick: () => void }) {
|
||||
const pillString = !["aircraft", "helicopter"].includes(props.blueprint.category) ? props.blueprint.type : props.blueprint.abilities;
|
||||
return (
|
||||
<div
|
||||
onClick={props.onClick}
|
||||
@@ -16,18 +17,16 @@ export function OlUnitListEntry(props: { icon: IconProp; blueprint: UnitBlueprin
|
||||
>
|
||||
<FontAwesomeIcon icon={props.icon} className="text-sm"></FontAwesomeIcon>
|
||||
<div className="flex-1 px-2 text-left font-normal">{props.blueprint.label}</div>
|
||||
<div
|
||||
className={`
|
||||
rounded-full bg-olympus-800 px-2 py-0.5 text-xs font-bold
|
||||
dark:text-olympus-50
|
||||
`}
|
||||
>
|
||||
{props.blueprint.era === "WW2"
|
||||
? "WW2"
|
||||
: props.blueprint.era.split(" ").map((word) => {
|
||||
return word.charAt(0).toLocaleUpperCase();
|
||||
})}
|
||||
</div>
|
||||
{pillString && (
|
||||
<div
|
||||
className={`
|
||||
rounded-full bg-olympus-800 px-2 py-0.5 text-xs font-bold
|
||||
dark:text-olympus-50
|
||||
`}
|
||||
>
|
||||
{!["aircraft", "helicopter"].includes(props.blueprint.category) ? props.blueprint.type : props.blueprint.abilities}
|
||||
</div>
|
||||
)}
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowRight}
|
||||
className={`
|
||||
|
||||
@@ -4,7 +4,7 @@ import { faSkull, faCamera, faFlag, faLink, faUnlink, faBars, faVolumeHigh } fro
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { OlDropdownItem, OlDropdown } from "../components/oldropdown";
|
||||
import { OlLabelToggle } from "../components/ollabeltoggle";
|
||||
import { getApp, IP, connectedToServer } from "../../olympusapp";
|
||||
import { getApp, IP } from "../../olympusapp";
|
||||
import {
|
||||
olButtonsVisibilityAirbase,
|
||||
olButtonsVisibilityAircraft,
|
||||
@@ -108,15 +108,6 @@ export function Header() {
|
||||
`}
|
||||
>
|
||||
{IP}
|
||||
<FontAwesomeIcon
|
||||
icon={connectedToServer ? faLink : faUnlink}
|
||||
data-connected={connectedToServer}
|
||||
className={`
|
||||
py-auto text-green-400
|
||||
dark:text-red-500
|
||||
data-[connected='true']:dark:text-green-400
|
||||
`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -42,24 +42,33 @@ export function SpawnMenu(props: { open: boolean; onClose: () => void; children?
|
||||
const [types, setTypes] = useState({ groundunit: [] as string[], navyunit: [] as string[] });
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedRole)
|
||||
setBlueprints(getApp()?.getUnitsManager().getDatabase().getByRole(selectedRole));
|
||||
else if (selectedType)
|
||||
setBlueprints(getApp()?.getUnitsManager().getDatabase().getByType(selectedType));
|
||||
else
|
||||
setBlueprints(getApp()?.getUnitsManager().getDatabase().getBlueprints())
|
||||
if (selectedRole) setBlueprints(getApp()?.getUnitsManager().getDatabase().getByRole(selectedRole));
|
||||
else if (selectedType) setBlueprints(getApp()?.getUnitsManager().getDatabase().getByType(selectedType));
|
||||
else setBlueprints(getApp()?.getUnitsManager().getDatabase().getBlueprints());
|
||||
}, [selectedRole, selectedType, openAccordion]);
|
||||
|
||||
useEffect(() => {
|
||||
UnitDatabaseLoadedEvent.on(() => {
|
||||
setRoles({
|
||||
aircraft: getApp()?.getUnitsManager().getDatabase().getRoles((unit) => unit.category === "aircraft"),
|
||||
helicopter: getApp()?.getUnitsManager().getDatabase().getRoles((unit) => unit.category === "helicopter"),
|
||||
aircraft: getApp()
|
||||
?.getUnitsManager()
|
||||
.getDatabase()
|
||||
.getRoles((unit) => unit.category === "aircraft"),
|
||||
helicopter: getApp()
|
||||
?.getUnitsManager()
|
||||
.getDatabase()
|
||||
.getRoles((unit) => unit.category === "helicopter"),
|
||||
});
|
||||
|
||||
setTypes({
|
||||
groundunit: getApp()?.getUnitsManager().getDatabase().getTypes((unit) => unit.category === "groundunit"),
|
||||
navyunit: getApp()?.getUnitsManager().getDatabase().getTypes((unit) => unit.category === "navyunit")
|
||||
groundunit: getApp()
|
||||
?.getUnitsManager()
|
||||
.getDatabase()
|
||||
.getTypes((unit) => unit.category === "groundunit"),
|
||||
navyunit: getApp()
|
||||
?.getUnitsManager()
|
||||
.getDatabase()
|
||||
.getTypes((unit) => unit.category === "navyunit"),
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
@@ -193,7 +202,7 @@ export function SpawnMenu(props: { open: boolean; onClose: () => void; children?
|
||||
</div>
|
||||
</OlAccordion>
|
||||
<OlAccordion
|
||||
title={`Surfact to Air Missiles (SAM sites)`}
|
||||
title={`Surface to Air Missiles (SAM sites)`}
|
||||
open={openAccordion == CategoryAccordion.SAM}
|
||||
onClick={() => {
|
||||
setOpenAccordion(openAccordion === CategoryAccordion.SAM ? CategoryAccordion.NONE : CategoryAccordion.SAM);
|
||||
@@ -208,7 +217,7 @@ export function SpawnMenu(props: { open: boolean; onClose: () => void; children?
|
||||
`}
|
||||
>
|
||||
{filteredBlueprints
|
||||
.filter((blueprint) => blueprint.category === "groundunit")
|
||||
.filter((blueprint) => blueprint.category === "groundunit" && blueprint.type === "SAM Site")
|
||||
.map((entry) => {
|
||||
return <OlUnitListEntry key={entry.name} icon={olButtonsVisibilityGroundunitSam} blueprint={entry} onClick={() => setBlueprint(entry)} />;
|
||||
})}
|
||||
@@ -230,7 +239,7 @@ export function SpawnMenu(props: { open: boolean; onClose: () => void; children?
|
||||
`}
|
||||
>
|
||||
{filteredBlueprints
|
||||
.filter((blueprint) => blueprint.category === "groundunit")
|
||||
.filter((blueprint) => blueprint.canAAA)
|
||||
.map((entry) => {
|
||||
return <OlUnitListEntry key={entry.name} icon={olButtonsVisibilityGroundunitSam} blueprint={entry} onClick={() => setBlueprint(entry)} />;
|
||||
})}
|
||||
@@ -248,9 +257,7 @@ export function SpawnMenu(props: { open: boolean; onClose: () => void; children?
|
||||
<div className="mb-2 flex flex-wrap gap-1">
|
||||
{types.groundunit
|
||||
.sort()
|
||||
.filter((type) => {
|
||||
return type !== "AAA" && type !== "SAM Site";
|
||||
})
|
||||
.filter((type) => type !== "SAM Site")
|
||||
.map((type) => {
|
||||
return (
|
||||
<div
|
||||
@@ -278,7 +285,7 @@ export function SpawnMenu(props: { open: boolean; onClose: () => void; children?
|
||||
`}
|
||||
>
|
||||
{filteredBlueprints
|
||||
.filter((blueprint) => blueprint.category === "groundunit")
|
||||
.filter((blueprint) => blueprint.category === "groundunit" && blueprint.type !== "SAM Site")
|
||||
.map((entry) => {
|
||||
return <OlUnitListEntry key={entry.name} icon={olButtonsVisibilityGroundunit} blueprint={entry} onClick={() => setBlueprint(entry)} />;
|
||||
})}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { OlRangeSlider } from "../components/olrangeslider";
|
||||
import { getApp } from "../../olympusapp";
|
||||
import { OlButtonGroup, OlButtonGroupItem } from "../components/olbuttongroup";
|
||||
import { OlCheckbox } from "../components/olcheckbox";
|
||||
import { ROEs, emissionsCountermeasures, reactionsToThreat } from "../../constants/constants";
|
||||
import { ROEs, altitudeIncrements, emissionsCountermeasures, maxAltitudeValues, minAltitudeValues, reactionsToThreat, speedIncrements } from "../../constants/constants";
|
||||
import { OlToggle } from "../components/oltoggle";
|
||||
import { OlCoalitionToggle } from "../components/olcoalitiontoggle";
|
||||
import {
|
||||
@@ -202,26 +202,28 @@ export function UnitControlMenu(props: { open: boolean; onClose: () => void }) {
|
||||
return category === "Helicopter";
|
||||
});
|
||||
|
||||
// TODO: use constants
|
||||
/* Speed/altitude increments */
|
||||
const minAltitude = 0;
|
||||
const minSpeed = 0;
|
||||
|
||||
let maxAltitude = 60000;
|
||||
let maxSpeed = 800;
|
||||
|
||||
let altitudeStep = 500;
|
||||
let speedStep = 10;
|
||||
let maxAltitude = maxAltitudeValues.aircraft;
|
||||
let maxSpeed = minAltitudeValues.aircraft;
|
||||
let speedStep = speedIncrements.aircraft;
|
||||
let altitudeStep = altitudeIncrements.aircraft;
|
||||
|
||||
if (everyUnitIsHelicopter) {
|
||||
maxAltitude = 20000;
|
||||
maxSpeed = 200;
|
||||
speedStep = 5;
|
||||
altitudeStep = 100;
|
||||
maxAltitude = maxAltitudeValues.helicopter;
|
||||
maxSpeed = minAltitudeValues.helicopter;
|
||||
speedStep = speedIncrements.helicopter;
|
||||
altitudeStep = altitudeIncrements.helicopter;
|
||||
}
|
||||
|
||||
if (everyUnitIsGround || everyUnitIsNavy) {
|
||||
maxSpeed = 60;
|
||||
speedStep = 1;
|
||||
else if (everyUnitIsGround) {
|
||||
maxSpeed = minAltitudeValues.groundunit;
|
||||
speedStep = speedIncrements.groundunit;
|
||||
}
|
||||
else if (everyUnitIsNavy) {
|
||||
maxSpeed = minAltitudeValues.navyunit;
|
||||
speedStep = speedIncrements.navyunit;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -654,7 +656,6 @@ export function UnitControlMenu(props: { open: boolean; onClose: () => void }) {
|
||||
</div>
|
||||
)}
|
||||
{/* ============== Rules of Engagement END ============== */}
|
||||
|
||||
{selectedCategories.every((category) => {
|
||||
return ["Aircraft", "Helicopter"].includes(category);
|
||||
}) && (
|
||||
|
||||
@@ -11,15 +11,15 @@ import { getApp } from "../../olympusapp";
|
||||
import { ftToM } from "../../other/utils";
|
||||
import { LatLng } from "leaflet";
|
||||
import { Airbase } from "../../mission/airbase";
|
||||
import { OlympusState, SpawnSubState } from "../../constants/constants";
|
||||
import { altitudeIncrements, groupUnitCount, maxAltitudeValues, minAltitudeValues, OlympusState, SpawnSubState } from "../../constants/constants";
|
||||
|
||||
export function UnitSpawnMenu(props: { blueprint: UnitBlueprint; spawnAtLocation: boolean; airbase?: Airbase | null; coalition?: Coalition }) {
|
||||
/* Compute the min and max values depending on the unit type */
|
||||
const minNumber = 1;
|
||||
const maxNumber = 4;
|
||||
const minAltitude = 0;
|
||||
const maxAltitude = 30000;
|
||||
const altitudeStep = 500;
|
||||
const maxNumber = groupUnitCount[props.blueprint.category];
|
||||
const minAltitude = minAltitudeValues[props.blueprint.category];
|
||||
const maxAltitude = maxAltitudeValues[props.blueprint.category];
|
||||
const altitudeStep = altitudeIncrements[props.blueprint.category];
|
||||
|
||||
/* State initialization */
|
||||
const [spawnCoalition, setSpawnCoalition] = useState("blue" as Coalition);
|
||||
@@ -53,7 +53,7 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint; spawnAtLocation
|
||||
},
|
||||
coalition: spawnCoalition,
|
||||
});
|
||||
getApp().setState(OlympusState.SPAWN, SpawnSubState.SPAWN_UNIT)
|
||||
getApp().setState(OlympusState.SPAWN, SpawnSubState.SPAWN_UNIT);
|
||||
} else {
|
||||
if (getApp().getState() === OlympusState.SPAWN) getApp().setState(OlympusState.IDLE);
|
||||
}
|
||||
@@ -141,98 +141,102 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint; spawnAtLocation
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className={`
|
||||
flex flex-row content-center items-center justify-between
|
||||
`}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span
|
||||
{["aircraft", "helicopter"].includes(props.blueprint.category) && (
|
||||
<>
|
||||
<div>
|
||||
<div
|
||||
className={`
|
||||
font-normal
|
||||
dark:text-white
|
||||
flex flex-row content-center items-center justify-between
|
||||
`}
|
||||
>
|
||||
Altitude
|
||||
</span>
|
||||
<span
|
||||
className={`
|
||||
font-bold
|
||||
dark:text-blue-500
|
||||
`}
|
||||
>{`${Intl.NumberFormat("en-US").format(spawnAltitude)} FT`}</span>
|
||||
</div>
|
||||
<OlLabelToggle toggled={spawnAltitudeType} leftLabel={"AGL"} rightLabel={"ASL"} onClick={() => setSpawnAltitudeType(!spawnAltitudeType)} />
|
||||
</div>
|
||||
<OlRangeSlider
|
||||
onChange={(ev) => setSpawnAltitude(Number(ev.target.value))}
|
||||
value={spawnAltitude}
|
||||
min={minAltitude}
|
||||
max={maxAltitude}
|
||||
step={altitudeStep}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex flex-row content-center justify-between">
|
||||
<span
|
||||
className={`
|
||||
h-8 font-normal
|
||||
dark:text-white
|
||||
`}
|
||||
>
|
||||
Role
|
||||
</span>
|
||||
</div>
|
||||
<OlDropdown label={spawnRole} className="w-full">
|
||||
{roles.map((role) => {
|
||||
return (
|
||||
<OlDropdownItem
|
||||
onClick={() => {
|
||||
setSpawnRole(role);
|
||||
setSpawnLoadout("");
|
||||
}}
|
||||
className={`w-full`}
|
||||
>
|
||||
{role}
|
||||
</OlDropdownItem>
|
||||
);
|
||||
})}
|
||||
</OlDropdown>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex flex-row content-center justify-between">
|
||||
<span
|
||||
className={`
|
||||
h-8 font-normal
|
||||
dark:text-white
|
||||
`}
|
||||
>
|
||||
Weapons
|
||||
</span>
|
||||
</div>
|
||||
<OlDropdown label={spawnLoadoutName} className={`w-full w-max-full`}>
|
||||
{loadouts.map((loadout) => {
|
||||
return (
|
||||
<OlDropdownItem
|
||||
onClick={() => {
|
||||
setSpawnLoadout(loadout.name);
|
||||
}}
|
||||
className={`w-full`}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span
|
||||
className={`
|
||||
w-full overflow-hidden text-ellipsis text-nowrap text-left
|
||||
w-max-full
|
||||
font-normal
|
||||
dark:text-white
|
||||
`}
|
||||
>
|
||||
{loadout.name}
|
||||
Altitude
|
||||
</span>
|
||||
</OlDropdownItem>
|
||||
);
|
||||
})}
|
||||
</OlDropdown>
|
||||
</div>
|
||||
<span
|
||||
className={`
|
||||
font-bold
|
||||
dark:text-blue-500
|
||||
`}
|
||||
>{`${Intl.NumberFormat("en-US").format(spawnAltitude)} FT`}</span>
|
||||
</div>
|
||||
<OlLabelToggle toggled={spawnAltitudeType} leftLabel={"AGL"} rightLabel={"ASL"} onClick={() => setSpawnAltitudeType(!spawnAltitudeType)} />
|
||||
</div>
|
||||
<OlRangeSlider
|
||||
onChange={(ev) => setSpawnAltitude(Number(ev.target.value))}
|
||||
value={spawnAltitude}
|
||||
min={minAltitude}
|
||||
max={maxAltitude}
|
||||
step={altitudeStep}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex flex-row content-center justify-between">
|
||||
<span
|
||||
className={`
|
||||
h-8 font-normal
|
||||
dark:text-white
|
||||
`}
|
||||
>
|
||||
Role
|
||||
</span>
|
||||
</div>
|
||||
<OlDropdown label={spawnRole} className="w-full">
|
||||
{roles.map((role) => {
|
||||
return (
|
||||
<OlDropdownItem
|
||||
onClick={() => {
|
||||
setSpawnRole(role);
|
||||
setSpawnLoadout("");
|
||||
}}
|
||||
className={`w-full`}
|
||||
>
|
||||
{role}
|
||||
</OlDropdownItem>
|
||||
);
|
||||
})}
|
||||
</OlDropdown>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex flex-row content-center justify-between">
|
||||
<span
|
||||
className={`
|
||||
h-8 font-normal
|
||||
dark:text-white
|
||||
`}
|
||||
>
|
||||
Weapons
|
||||
</span>
|
||||
</div>
|
||||
<OlDropdown label={spawnLoadoutName} className={`w-full w-max-full`}>
|
||||
{loadouts.map((loadout) => {
|
||||
return (
|
||||
<OlDropdownItem
|
||||
onClick={() => {
|
||||
setSpawnLoadout(loadout.name);
|
||||
}}
|
||||
className={`w-full`}
|
||||
>
|
||||
<span
|
||||
className={`
|
||||
w-full overflow-hidden text-ellipsis text-nowrap
|
||||
text-left w-max-full
|
||||
`}
|
||||
>
|
||||
{loadout.name}
|
||||
</span>
|
||||
</OlDropdownItem>
|
||||
);
|
||||
})}
|
||||
</OlDropdown>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{spawnLoadout && spawnLoadout.items.length > 0 && (
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user