mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Merge pull request #919 from Pax1601/904-add-unit-loadoutfuelhealth-panel-to-unit-control-panel
904 add unit loadoutfuelhealth panel to unit control panel
This commit is contained in:
commit
040476107a
@ -135,7 +135,6 @@ export interface Offset {
|
||||
|
||||
export interface UnitData {
|
||||
category: string;
|
||||
categoryDisplayName: string;
|
||||
ID: number;
|
||||
alive: boolean;
|
||||
human: boolean;
|
||||
|
||||
@ -601,3 +601,55 @@ export function getFunctionArguments(func) {
|
||||
if (result === null) result = [];
|
||||
return result;
|
||||
}
|
||||
|
||||
export function filterBlueprintsByLabel(
|
||||
blueprints: { [key: string]: UnitBlueprint },
|
||||
filterString: string
|
||||
) {
|
||||
var filteredBlueprints: { [key: string]: UnitBlueprint } = {};
|
||||
if (blueprints) {
|
||||
Object.entries(blueprints).forEach(([key, value]) => {
|
||||
if (
|
||||
value.enabled &&
|
||||
(filterString === "" || value.label.includes(filterString))
|
||||
)
|
||||
filteredBlueprints[key] = value;
|
||||
});
|
||||
}
|
||||
return filteredBlueprints;
|
||||
}
|
||||
|
||||
export function getUnitsByLabel(filterString: string) {
|
||||
/* Filter aircrafts, helicopters, and navyunits */
|
||||
const filteredAircraft = filterBlueprintsByLabel(
|
||||
getApp()?.getAircraftDatabase()?.blueprints,
|
||||
filterString
|
||||
);
|
||||
const filteredHelicopters = filterBlueprintsByLabel(
|
||||
getApp()?.getHelicopterDatabase()?.blueprints,
|
||||
filterString
|
||||
);
|
||||
const filteredNavyUnits = filterBlueprintsByLabel(
|
||||
getApp()?.getNavyUnitDatabase()?.blueprints,
|
||||
filterString
|
||||
);
|
||||
|
||||
/* Split ground units between air defence and all others */
|
||||
var filteredAirDefense: { [key: string]: UnitBlueprint } = {};
|
||||
var filteredGroundUnits: { [key: string]: UnitBlueprint } = {};
|
||||
Object.keys(getApp()?.getGroundUnitDatabase()?.blueprints ?? {}).forEach(
|
||||
(key) => {
|
||||
var blueprint = getApp()?.getGroundUnitDatabase()?.blueprints[key];
|
||||
var type = blueprint.label;
|
||||
if (/\bAAA|SAM\b/.test(type) || /\bmanpad|stinger\b/i.test(type)) {
|
||||
filteredAirDefense[key] = blueprint;
|
||||
} else {
|
||||
filteredGroundUnits[key] = blueprint;
|
||||
}
|
||||
}
|
||||
);
|
||||
filteredAirDefense = filterBlueprintsByLabel(filteredAirDefense, filterString);
|
||||
filteredGroundUnits = filterBlueprintsByLabel(filteredGroundUnits, filterString);
|
||||
|
||||
return [filteredAircraft, filteredHelicopters, filteredAirDefense, filteredGroundUnits, filteredNavyUnits]
|
||||
}
|
||||
@ -2,6 +2,8 @@ import React, { ChangeEvent } from "react";
|
||||
|
||||
export function OlCheckbox(props: {
|
||||
checked: boolean;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
}) {
|
||||
return (
|
||||
@ -10,7 +12,9 @@ export function OlCheckbox(props: {
|
||||
type="checkbox"
|
||||
checked={props.checked}
|
||||
value=""
|
||||
disabled={props.disabled ?? false}
|
||||
className={`
|
||||
${props.className ?? ""}
|
||||
my-auto h-4 w-4 cursor-pointer rounded border-gray-300 bg-gray-100
|
||||
text-blue-600
|
||||
dark:border-gray-600 dark:bg-gray-700 dark:ring-offset-gray-800
|
||||
|
||||
@ -1,17 +1,21 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import React, { useState, useEffect, useRef, MutableRefObject } from "react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { IconProp } from "@fortawesome/fontawesome-svg-core";
|
||||
|
||||
export function OlDropdown(props: {
|
||||
className: string;
|
||||
className?: string;
|
||||
leftIcon?: IconProp;
|
||||
rightIcon?: IconProp;
|
||||
label: string;
|
||||
label?: string;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
buttonRef?: MutableRefObject<null> | null;
|
||||
open?: boolean;
|
||||
}) {
|
||||
var [open, setOpen] = useState(false);
|
||||
var [open, setOpen] =
|
||||
props.open !== undefined ? [props.open, () => {}] : useState(false);
|
||||
var contentRef = useRef(null);
|
||||
var buttonRef = useRef(null);
|
||||
var buttonRef =
|
||||
props.buttonRef !== undefined ? props.buttonRef : useRef(null);
|
||||
|
||||
function setPosition(content: HTMLDivElement, button: HTMLButtonElement) {
|
||||
/* Reset the position of the content */
|
||||
@ -19,21 +23,7 @@ export function OlDropdown(props: {
|
||||
content.style.top = "0px";
|
||||
content.style.height = "";
|
||||
|
||||
/* Get the position and size of the button */
|
||||
var [bxl, byt, bxr, byb, bw, bh] = [
|
||||
button.getBoundingClientRect().x,
|
||||
button.getBoundingClientRect().y,
|
||||
button.getBoundingClientRect().x + button.clientWidth,
|
||||
button.getBoundingClientRect().y + button.clientHeight,
|
||||
button.clientWidth,
|
||||
button.clientHeight,
|
||||
];
|
||||
|
||||
/* Set the minimum and maximum width to be equal to the button width */
|
||||
content.style.minWidth = `${bw}px`;
|
||||
content.style.maxWidth = `${bw}px`;
|
||||
|
||||
/* Get the position and size of the content element */
|
||||
/* Get the position and size of the button and the content elements */
|
||||
var [cxl, cyt, cxr, cyb, cw, ch] = [
|
||||
content.getBoundingClientRect().x,
|
||||
content.getBoundingClientRect().y,
|
||||
@ -42,6 +32,14 @@ export function OlDropdown(props: {
|
||||
content.clientWidth,
|
||||
content.clientHeight,
|
||||
];
|
||||
var [bxl, byt, bxr, byb, bbw, bh] = [
|
||||
button.getBoundingClientRect().x,
|
||||
button.getBoundingClientRect().y,
|
||||
button.getBoundingClientRect().x + button.clientWidth,
|
||||
button.getBoundingClientRect().y + button.clientHeight,
|
||||
button.clientWidth,
|
||||
button.clientHeight,
|
||||
];
|
||||
|
||||
/* Limit the maximum height */
|
||||
if (ch > 400) {
|
||||
@ -70,10 +68,11 @@ export function OlDropdown(props: {
|
||||
/* Apply the offset */
|
||||
content.style.left = `${offsetX}px`;
|
||||
content.style.top = `${offsetY}px`;
|
||||
content.style.width = `${bbw}px`;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (contentRef.current && buttonRef.current) {
|
||||
if (contentRef.current && buttonRef?.current) {
|
||||
const content = contentRef.current as HTMLDivElement;
|
||||
const button = buttonRef.current as HTMLButtonElement;
|
||||
|
||||
@ -94,53 +93,57 @@ export function OlDropdown(props: {
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={(props.className ?? "") + "relative"}>
|
||||
<button
|
||||
ref={buttonRef}
|
||||
onClick={() => {
|
||||
setOpen(!open);
|
||||
}}
|
||||
className={`
|
||||
inline-flex w-full items-center justify-between rounded-lg border
|
||||
bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white
|
||||
dark:border-gray-700 dark:bg-gray-700 dark:text-gray-100
|
||||
dark:hover:bg-gray-600
|
||||
hover:bg-blue-800
|
||||
`}
|
||||
type="button"
|
||||
>
|
||||
{props.leftIcon && (
|
||||
<FontAwesomeIcon icon={props.leftIcon} className={`mr-3`} />
|
||||
)}
|
||||
<span className="overflow-hidden text-ellipsis text-nowrap">
|
||||
{props.label}
|
||||
</span>
|
||||
<svg
|
||||
<div
|
||||
className={props.className ?? ""}
|
||||
>
|
||||
{props.buttonRef === undefined && (
|
||||
<button
|
||||
ref={buttonRef}
|
||||
onClick={() => {
|
||||
setOpen(!open);
|
||||
}}
|
||||
className={`
|
||||
ml-auto ms-3 h-2.5 w-2.5 flex-none transition-transform
|
||||
data-[open='true']:-scale-y-100
|
||||
inline-flex w-full items-center justify-between rounded-lg border
|
||||
bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white
|
||||
dark:border-gray-700 dark:bg-gray-700 dark:text-gray-100
|
||||
dark:hover:bg-gray-600
|
||||
hover:bg-blue-800
|
||||
`}
|
||||
data-open={open}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 10 6"
|
||||
type="button"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="m1 1 4 4 4-4"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
{props.leftIcon && (
|
||||
<FontAwesomeIcon icon={props.leftIcon} className={`mr-3`} />
|
||||
)}
|
||||
<span className="overflow-hidden text-ellipsis text-nowrap">
|
||||
{props.label ?? ""}
|
||||
</span>
|
||||
<svg
|
||||
className={`
|
||||
ml-auto ms-3 h-2.5 w-2.5 flex-none transition-transform
|
||||
data-[open='true']:-scale-y-100
|
||||
`}
|
||||
data-open={open}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 10 6"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
d="m1 1 4 4 4-4"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<div
|
||||
ref={contentRef}
|
||||
data-open={open}
|
||||
className={`
|
||||
absolute z-ui-4 divide-y divide-gray-100 overflow-y-scroll
|
||||
no-scrollbar rounded-lg bg-white p-2 shadow
|
||||
absolute divide-y divide-gray-100 overflow-y-scroll no-scrollbar
|
||||
rounded-lg bg-white p-2 shadow
|
||||
dark:bg-gray-700
|
||||
data-[open='false']:hidden
|
||||
`}
|
||||
@ -165,8 +168,8 @@ export function OlDropdownItem(props) {
|
||||
onClick={props.onClick ?? (() => {})}
|
||||
className={`
|
||||
${props.className ?? ""}
|
||||
flex cursor-pointer select-none flex-row content-center rounded-md px-4
|
||||
py-2
|
||||
flex w-full cursor-pointer select-none flex-row content-center
|
||||
rounded-md px-4 py-2
|
||||
dark:hover:bg-gray-600 dark:hover:text-white
|
||||
hover:bg-gray-100
|
||||
`}
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
import { faMultiply, faSearch } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import React, { ChangeEvent, useId, useRef } from "react";
|
||||
import React, { useId, useRef } from "react";
|
||||
|
||||
export function OlSearchBar(props: {
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
onChange: (e: string) => void;
|
||||
text: string;
|
||||
}) {
|
||||
const searchId = useId();
|
||||
const inputRef = useRef(null);
|
||||
|
||||
function resetSearch() {
|
||||
inputRef.current && ((inputRef.current as HTMLInputElement).value = "");
|
||||
props.onChange("");
|
||||
}
|
||||
|
||||
return (
|
||||
@ -36,7 +38,7 @@ export function OlSearchBar(props: {
|
||||
type="search"
|
||||
ref={inputRef}
|
||||
id={searchId}
|
||||
onChange={props.onChange}
|
||||
onChange={(e) => props.onChange(e.currentTarget.value)}
|
||||
className={`
|
||||
mb-2 block w-full rounded-full border border-gray-300 bg-gray-50 p-3
|
||||
ps-10 text-sm text-gray-900
|
||||
@ -46,6 +48,7 @@ export function OlSearchBar(props: {
|
||||
focus:border-blue-500 focus:ring-blue-500
|
||||
`}
|
||||
placeholder="Search"
|
||||
value={props.text}
|
||||
required
|
||||
/>
|
||||
<FontAwesomeIcon
|
||||
|
||||
@ -70,7 +70,7 @@ export function Menu(props: {
|
||||
</div>
|
||||
{props.canBeHidden == true && (
|
||||
<div className={`
|
||||
flex h-8 justify-center z-ui-6 pointer-events-auto backdrop-blur-lg
|
||||
flex h-8 justify-center z-ui-4 pointer-events-auto backdrop-blur-lg
|
||||
backdrop-grayscale
|
||||
dark:bg-olympus-800/90
|
||||
`} onClick={() => setHide(!hide)}>
|
||||
|
||||
@ -35,18 +35,17 @@ export function Header() {
|
||||
const [scrolledLeft, setScrolledLeft] = useState(true);
|
||||
const [scrolledRight, setScrolledRight] = useState(false);
|
||||
|
||||
/* Initialize the "scroll" position of the element */
|
||||
var scrollRef = useRef(null);
|
||||
useEffect(() => {
|
||||
if (scrollRef.current) {
|
||||
onScroll(scrollRef.current);
|
||||
}
|
||||
});
|
||||
/* Initialize the "scroll" position of the element */
|
||||
var scrollRef = useRef(null);
|
||||
useEffect(() => {
|
||||
if (scrollRef.current) {
|
||||
onScroll(scrollRef.current);
|
||||
}
|
||||
});
|
||||
|
||||
function onScroll(el) {
|
||||
const sl = el.scrollLeft;
|
||||
const sr =
|
||||
el.scrollWidth - el.scrollLeft - el.clientWidth;
|
||||
const sr = el.scrollWidth - el.scrollLeft - el.clientWidth;
|
||||
|
||||
sl < 1 && !scrolledLeft && setScrolledLeft(true);
|
||||
sl > 1 && scrolledLeft && setScrolledLeft(false);
|
||||
@ -249,29 +248,28 @@ export function Header() {
|
||||
onClick={() => {}}
|
||||
tooltip="Activate/deactivate camera plugin"
|
||||
/>
|
||||
<OlDropdown label={appState.activeMapSource} className="w-40">
|
||||
<OlDropdown label={appState.activeMapSource} className="w-60">
|
||||
{appState.mapSources.map((source) => {
|
||||
return (
|
||||
<OlDropdownItem
|
||||
key={source}
|
||||
className="w-52"
|
||||
onClick={() => getApp().getMap().setLayerName(source)}
|
||||
>
|
||||
{source}
|
||||
<div className="truncate">{source}</div>
|
||||
</OlDropdownItem>
|
||||
);
|
||||
})}
|
||||
</OlDropdown>
|
||||
</div>
|
||||
{!scrolledRight && (
|
||||
<FaChevronRight
|
||||
className={`
|
||||
absolute right-0 h-full w-6 rounded-lg px-2 py-3.5
|
||||
text-gray-200 z-ui-1
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
<FaChevronRight
|
||||
className={`
|
||||
absolute right-0 h-full w-6 rounded-lg px-2 py-3.5
|
||||
text-gray-200 z-ui-1
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
</nav>
|
||||
)}
|
||||
</EventsConsumer>
|
||||
|
||||
@ -11,15 +11,8 @@ import {
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { EventsConsumer } from "../../eventscontext";
|
||||
import { StateConsumer } from "../../statecontext";
|
||||
import { IDLE, SPAWN_UNIT } from "../../constants/constants";
|
||||
|
||||
export function SideBar() {
|
||||
const [mapState, setMapState] = useState(IDLE);
|
||||
|
||||
document.addEventListener("mapStateChanged", (ev) => {
|
||||
setMapState((ev as CustomEvent).detail);
|
||||
});
|
||||
|
||||
return (
|
||||
<StateConsumer>
|
||||
{(appState) => (
|
||||
|
||||
@ -16,26 +16,10 @@ import {
|
||||
olButtonsVisibilityNavyunit,
|
||||
} from "../components/olicons";
|
||||
import { IDLE, SPAWN_UNIT } from "../../constants/constants";
|
||||
import { getUnitsByLabel } from "../../other/utils";
|
||||
|
||||
library.add(faPlus);
|
||||
|
||||
function filterUnits(
|
||||
blueprints: { [key: string]: UnitBlueprint },
|
||||
filterString: string
|
||||
) {
|
||||
var filteredUnits = {};
|
||||
if (blueprints) {
|
||||
Object.entries(blueprints).forEach(([key, value]) => {
|
||||
if (
|
||||
value.enabled &&
|
||||
(filterString === "" || value.label.includes(filterString))
|
||||
)
|
||||
filteredUnits[key] = value;
|
||||
});
|
||||
}
|
||||
return filteredUnits;
|
||||
}
|
||||
|
||||
export function SpawnMenu(props: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
@ -44,36 +28,13 @@ export function SpawnMenu(props: {
|
||||
var [blueprint, setBlueprint] = useState(null as null | UnitBlueprint);
|
||||
var [filterString, setFilterString] = useState("");
|
||||
|
||||
/* Filter aircrafts, helicopters, and navyunits */
|
||||
const filteredAircraft = filterUnits(
|
||||
getApp()?.getAircraftDatabase()?.blueprints,
|
||||
filterString
|
||||
);
|
||||
const filteredHelicopters = filterUnits(
|
||||
getApp()?.getHelicopterDatabase()?.blueprints,
|
||||
filterString
|
||||
);
|
||||
const filteredNavyUnits = filterUnits(
|
||||
getApp()?.getNavyUnitDatabase()?.blueprints,
|
||||
filterString
|
||||
);
|
||||
|
||||
/* Split ground units between air defence and all others */
|
||||
var filteredAirDefense = {};
|
||||
var filteredGroundUnits = {};
|
||||
Object.keys(getApp()?.getGroundUnitDatabase()?.blueprints ?? {}).forEach(
|
||||
(key) => {
|
||||
var blueprint = getApp()?.getGroundUnitDatabase()?.blueprints[key];
|
||||
var type = blueprint.label;
|
||||
if (/\bAAA|SAM\b/.test(type) || /\bmanpad|stinger\b/i.test(type)) {
|
||||
filteredAirDefense[key] = blueprint;
|
||||
} else {
|
||||
filteredGroundUnits[key] = blueprint;
|
||||
}
|
||||
}
|
||||
);
|
||||
filteredAirDefense = filterUnits(filteredAirDefense, filterString);
|
||||
filteredGroundUnits = filterUnits(filteredGroundUnits, filterString);
|
||||
const [
|
||||
filteredAircraft,
|
||||
filteredHelicopters,
|
||||
filteredAirDefense,
|
||||
filteredGroundUnits,
|
||||
filteredNavyUnits,
|
||||
] = getUnitsByLabel(filterString);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.open) {
|
||||
@ -97,22 +58,23 @@ export function SpawnMenu(props: {
|
||||
<>
|
||||
{blueprint === null && (
|
||||
<div className="p-5">
|
||||
<OlSearchBar onChange={(ev) => setFilterString(ev.target.value)} />
|
||||
<OlSearchBar
|
||||
onChange={(value) => setFilterString(value)}
|
||||
text={filterString}
|
||||
/>
|
||||
<OlAccordion title={`Aircraft`}>
|
||||
<div
|
||||
className={`
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}
|
||||
>
|
||||
{Object.keys(filteredAircraft).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getAircraftDatabase().blueprints[key];
|
||||
{Object.entries(filteredAircraft).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={key}
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityAircraft}
|
||||
blueprint={blueprint}
|
||||
onClick={() => setBlueprint(blueprint)}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@ -124,15 +86,13 @@ export function SpawnMenu(props: {
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}
|
||||
>
|
||||
{Object.keys(filteredHelicopters).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getHelicopterDatabase().blueprints[key];
|
||||
{Object.entries(filteredHelicopters).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={key}
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityHelicopter}
|
||||
blueprint={blueprint}
|
||||
onClick={() => setBlueprint(blueprint)}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@ -144,15 +104,13 @@ export function SpawnMenu(props: {
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}
|
||||
>
|
||||
{Object.keys(filteredAirDefense).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getGroundUnitDatabase().blueprints[key];
|
||||
{Object.entries(filteredAirDefense).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={key}
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityGroundunitSam}
|
||||
blueprint={blueprint}
|
||||
onClick={() => setBlueprint(blueprint)}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@ -164,15 +122,13 @@ export function SpawnMenu(props: {
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}
|
||||
>
|
||||
{Object.keys(filteredGroundUnits).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getGroundUnitDatabase().blueprints[key];
|
||||
{Object.entries(filteredGroundUnits).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={key}
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityGroundunit}
|
||||
blueprint={blueprint}
|
||||
onClick={() => setBlueprint(blueprint)}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@ -184,15 +140,13 @@ export function SpawnMenu(props: {
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}
|
||||
>
|
||||
{Object.keys(filteredNavyUnits).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getNavyUnitDatabase().blueprints[key];
|
||||
{Object.entries(filteredNavyUnits).map((entry) => {
|
||||
return (
|
||||
<OlUnitEntryList
|
||||
key={key}
|
||||
key={entry[0]}
|
||||
icon={olButtonsVisibilityNavyunit}
|
||||
blueprint={blueprint}
|
||||
onClick={() => setBlueprint(blueprint)}
|
||||
blueprint={entry[1]}
|
||||
onClick={() => setBlueprint(entry[1])}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,7 @@ export function UI() {
|
||||
var [mapSources, setMapSources] = useState([] as string[]);
|
||||
var [activeMapSource, setActiveMapSource] = useState("");
|
||||
var [mapBoxSelection, setMapBoxSelection] = useState(false);
|
||||
var [mapState, setMapState] = useState(IDLE);
|
||||
|
||||
document.addEventListener("hiddenTypesChanged", (ev) => {
|
||||
setMapHiddenTypes({ ...getApp().getMap().getHiddenTypes() });
|
||||
@ -64,9 +65,10 @@ export function UI() {
|
||||
});
|
||||
|
||||
document.addEventListener("mapStateChanged", (ev) => {
|
||||
if ((ev as CustomEvent).detail == IDLE) {
|
||||
if ((ev as CustomEvent).detail === IDLE && mapState !== IDLE)
|
||||
hideAllMenus();
|
||||
}
|
||||
|
||||
setMapState(String((ev as CustomEvent).detail))
|
||||
});
|
||||
|
||||
document.addEventListener("mapSourceChanged", (ev) => {
|
||||
|
||||
@ -443,18 +443,6 @@ export abstract class Unit extends CustomMarker {
|
||||
*/
|
||||
abstract getDefaultMarker(): string;
|
||||
|
||||
/** Get the category but for display use - for the user. (i.e. has spaces in it)
|
||||
*
|
||||
* @returns string
|
||||
*/
|
||||
getCategoryLabel() {
|
||||
return (
|
||||
GROUND_UNIT_AIR_DEFENCE_REGEX.test(this.getType())
|
||||
? "Air Defence"
|
||||
: this.getCategory()
|
||||
).replace(/([a-z])([A-Z])/g, "$1 $2");
|
||||
}
|
||||
|
||||
/********************** Unit data *************************/
|
||||
/** This function is called by the units manager to update all the data coming from the backend. It reads the binary raw data using a DataExtractor
|
||||
*
|
||||
@ -657,7 +645,6 @@ export abstract class Unit extends CustomMarker {
|
||||
getData(): UnitData {
|
||||
return {
|
||||
category: this.getCategory(),
|
||||
categoryDisplayName: this.getCategoryLabel(),
|
||||
ID: this.ID,
|
||||
alive: this.#alive,
|
||||
human: this.#human,
|
||||
|
||||
@ -66,7 +66,7 @@ module.exports = function (configLocation) {
|
||||
isActiveAWACS: false,
|
||||
onOff: true,
|
||||
followRoads: false,
|
||||
fuel: 50,
|
||||
fuel: 10,
|
||||
desiredSpeed: 300,
|
||||
desiredSpeedType: 1,
|
||||
desiredAltitude: 1000,
|
||||
@ -87,7 +87,19 @@ module.exports = function (configLocation) {
|
||||
prohibitAirWpn: false,
|
||||
prohibitJettison: false,
|
||||
},
|
||||
ammo: [],
|
||||
ammo: [{
|
||||
quantity: 2,
|
||||
name: "A super nice missile",
|
||||
guidance: 1,
|
||||
category: 1,
|
||||
missileCategory: 1
|
||||
}, {
|
||||
quantity: 4,
|
||||
name: "A less nice missile",
|
||||
guidance: 1,
|
||||
category: 1,
|
||||
missileCategory: 1
|
||||
}],
|
||||
contacts: [],
|
||||
activePath: [{ lat: 37.1, lng: -116.1 }],
|
||||
isLeader: true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user