Merge pull request #449 from Pax1601/small-issues

Added "land at point" state for helicopters
This commit is contained in:
Pax1601 2023-10-10 17:11:05 +02:00 committed by GitHub
commit c26691c2fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 210 additions and 8 deletions

View File

@ -265,9 +265,9 @@
}
[data-object|="unit"][data-state="attack"] .unit-state,
[data-object|="unit"][data-state="bombing point"] .unit-state,
[data-object|="unit"][data-state="carpet bombing"] .unit-state,
[data-object|="unit"][data-state="firing at area"] .unit-state {
[data-object|="unit"][data-state="bomb-point"] .unit-state,
[data-object|="unit"][data-state="carpet-bombing"] .unit-state,
[data-object|="unit"][data-state="fire-at-area"] .unit-state {
background-image: url("/resources/theme/images/states/attack.svg");
}
@ -287,6 +287,10 @@
background-image: url("/resources/theme/images/states/dcs.svg");
}
[data-object|="unit"][data-state="land-at-point"] .unit-state {
background-image: url("/resources/theme/images/states/land-at-point.svg");
}
[data-object|="unit"][data-state="no-task"] .unit-state {
background-image: url("/resources/theme/images/states/no-task.svg");
}

View File

@ -420,6 +420,10 @@
content: url("/resources/theme/images/icons/group-navy.svg");
}
#land-at-point::before {
content: url("/resources/theme/images/icons/land-at-point.svg");
}
#trail::before {
content: url("/resources/theme/images/icons/trail.svg");
}

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
version="1.1"
id="svg7234"
sodipodi:docname="land-at-point.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata
id="metadata6">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs7238" />
<sodipodi:namedview
id="namedview7236"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="18.495262"
inkscape:cx="12.030108"
inkscape:cy="17.220627"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg7234"
inkscape:pageshadow="2"
width="512px" />
<path
inkscape:connector-curvature="0"
d="m 3.4418938,1.8579231 c 0,-0.4470615 0.3331285,-0.8082476 0.7454662,-0.8082476 h 8.945519 c 0.412333,0 0.745462,0.3611861 0.745462,0.8082476 0,0.4470624 -0.333129,0.8082443 -0.745462,0.8082443 H 9.4055765 v 1.616493 h 0.7454615 c 2.059333,0 3.727303,1.80845 3.727303,4.04123 v 1.616491 c 0,0.4470596 -0.333129,0.8082466 -0.745462,0.8082466 H 9.4055765 7.9146585 c -0.468246,0 -0.910858,-0.239949 -1.192738,-0.646596 L 5.0586105,7.6974974 C 4.9770785,7.5787864 4.865263,7.4878614 4.7394601,7.4322944 L 1.5596118,6.0532234 C 1.3382988,5.9572434 1.1705709,5.7501304 1.1123358,5.4975524 L 0.57653646,3.1687964 c -0.0605718,-0.255102 0.1188069,-0.502629 0.36108,-0.502629 H 1.5782493 c 0.2352817,0 0.45659,0.118712 0.5963664,0.323301 l 0.894552,1.293192 H 7.9146585 V 2.6661674 H 4.18736 c -0.4123377,0 -0.7454662,-0.3611819 -0.7454662,-0.8082443 z m 5.9636827,7.2742113 h 2.9818415 v -0.808244 c 0,-1.338658 -1.001708,-2.424737 -2.23638,-2.424737 H 9.4055765 Z m 5.7447015,2.6621596 c 0.291199,0.315723 0.291199,0.828456 0,1.144173 l -0.09085,0.09851 c -0.559097,0.606184 -1.318536,0.947164 -2.108255,0.947164 H 6.4237353 c -0.4123284,0 -0.7454616,-0.361187 -0.7454616,-0.808246 0,-0.447061 0.3331332,-0.808248 0.7454616,-0.808248 h 6.5274377 c 0.396023,0 0.775745,-0.169226 1.055293,-0.472318 l 0.09085,-0.09851 c 0.291199,-0.31572 0.764099,-0.31572 1.055293,0 z"
id="path1174-3"
style="fill:#202831;fill-opacity:1;stroke-width:0.0290252" />
<path
style="fill:none;stroke:#000000;stroke-width:1.07268px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="M 0.90212206,15.260973 H 15.104269"
id="path855" />
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="17"
height="17"
viewBox="0 0 17 17"
fill="none"
version="1.1"
id="svg6"
sodipodi:docname="land-at-point.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs10" />
<sodipodi:namedview
id="namedview8"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="24.470588"
inkscape:cx="5.2512019"
inkscape:cy="15.018029"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
style="fill:none;stroke:#2f2f2f;stroke-width:6.6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 4.9812012,10.145404 8.4655861,13.629789 11.998366,10.09701"
id="path1044-2" />
<path
style="fill:none;stroke:#2f2f2f;stroke-width:6.6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 8.4655861,13.629789 V 3.3702107"
id="path1046-6" />
<path
style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 4.9812012,10.145404 8.4655865,13.629789 11.998366,10.09701"
id="path1044" />
<path
style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 8.4655865,13.629789 V 3.3702106"
id="path1046" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -20,7 +20,7 @@ export const IRST = 8;
export const RWR = 16;
export const DLINK = 32;
export const states: string[] = ["none", "idle", "reach-destination", "attack", "follow", "land", "refuel", "AWACS", "tanker", "bomb-point", "carpet-bomb", "bomb-building", "fire-at-area", "simulate-fire-fight"];
export const states: string[] = ["none", "idle", "reach-destination", "attack", "follow", "land", "refuel", "AWACS", "tanker", "bomb-point", "carpet-bomb", "bomb-building", "fire-at-area", "simulate-fire-fight", "scenic-aaa", "miss-on-purpose", "land-at-point"];
export const ROEs: string[] = ["free", "designated", "", "return", "hold"];
export const reactionsToThreat: string[] = ["none", "manoeuvre", "passive", "evade"];
export const emissionsCountermeasures: string[] = ["silent", "attack", "defend", "free"];

View File

@ -24,8 +24,8 @@ import { TouchBoxSelect } from "./touchboxselect";
import { DestinationPreviewHandle } from "./markers/destinationpreviewHandle";
var hasTouchScreen = false;
if ("maxTouchPoints" in navigator)
hasTouchScreen = navigator.maxTouchPoints > 0;
//if ("maxTouchPoints" in navigator)
// hasTouchScreen = navigator.maxTouchPoints > 0;
if (hasTouchScreen)
L.Map.addInitHook('addHandler', 'boxSelect', TouchBoxSelect);
@ -607,6 +607,10 @@ export class Map extends L.Map {
const selectedUnitTypes = getApp().getUnitsManager().getSelectedUnitsCategories();
if (selectedUnitTypes.length === 1 && ["Aircraft", "Helicopter"].includes(selectedUnitTypes[0])) {
if (selectedUnitTypes[0] === "Helicopter") {
options["land-at-point"] = { text: "Land here", tooltip: "Land at this precise location" };
}
if (selectedUnits.every((unit: Unit) => { return unit.canFulfillRole(["CAS", "Strike"]) })) {
options["bomb"] = { text: "Precision bombing", tooltip: "Precision bombing of a specific point" };
options["carpet-bomb"] = { text: "Carpet bombing", tooltip: "Carpet bombing close to a point" };
@ -646,6 +650,10 @@ export class Map extends L.Map {
getApp().getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
getApp().getUnitsManager().selectedUnitsSimulateFireFight(this.getMouseCoordinates());
}
else if (option === "land-at-point") {
getApp().getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
getApp().getUnitsManager().selectedUnitsLandAtPoint(this.getMouseCoordinates());
}
});
}
}, 150);

View File

@ -351,6 +351,12 @@ export class ServerManager {
this.PUT(data, callback);
}
landAtPoint(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) {
var command = { "ID": ID, "location": latlng }
var data = { "landAtPoint": command }
this.PUT(data, callback);
}
setAdvacedOptions(ID: number, isTanker: boolean, isAWACS: boolean, TACAN: TACAN, radio: Radio, generalSettings: GeneralSettings, callback: CallableFunction = () => {}) {
var command = {
"ID": ID,

View File

@ -779,6 +779,10 @@ export class Unit extends CustomMarker {
getApp().getServerManager().missOnPurpose(this.ID, coalition);
}
landAtPoint(latlng: LatLng) {
getApp().getServerManager().landAtPoint(this.ID, latlng);
}
/***********************************************/
getActions(): { [key: string]: { text: string, tooltip: string, type: string } } {
/* To be implemented by child classes */ // TODO make Unit an abstract class

View File

@ -666,6 +666,19 @@ export class UnitsManager {
this.#showActionMessage(selectedUnits, `unit set to perform miss on purpose AAA`);
}
/** Instruct units to land at specific point
*
* @param latlng Point where to land
*/
selectedUnitsLandAtPoint(latlng: LatLng) {
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
for (let idx in selectedUnits) {
selectedUnits[idx].landAtPoint(latlng);
}
this.#showActionMessage(selectedUnits, `unit simulating fire fight`);
}
/*********************** Control operations on selected units ************************/
/** See getUnitsCategories for more info
*

View File

@ -1,6 +1,6 @@
local version = "v0.4.4-alpha"
local debug = false -- True enables debug printing using DCS messages
local debug = true -- True enables debug printing using DCS messages
-- .dll related variables
Olympus.OlympusDLL = nil
@ -260,6 +260,15 @@ function Olympus.buildTask(groupName, options)
}
}
end
-- Land at a specific point
elseif options['id'] == 'LandAtPoint' then
local point = coord.LLtoLO(options['lat'], options['lng'], 0)
task = {
id = 'Land',
params = {
point = {x = point.x, y = point.z},
}
}
end
end
return task

View File

@ -68,7 +68,8 @@ namespace State
FIRE_AT_AREA,
SIMULATE_FIRE_FIGHT,
SCENIC_AAA,
MISS_ON_PURPOSE
MISS_ON_PURPOSE,
LAND_AT_POINT
};
};

View File

@ -69,6 +69,9 @@ void AirUnit::setState(unsigned char newState)
setTargetPosition(Coords(NULL));
break;
}
case State::LAND_AT_POINT: {
break;
}
default:
break;
}
@ -125,6 +128,10 @@ void AirUnit::setState(unsigned char newState)
resetActiveDestination();
break;
}
case State::LAND_AT_POINT: {
resetActiveDestination();
break;
}
default:
break;
}
@ -340,6 +347,24 @@ void AirUnit::AIloop()
}
break;
}
case State::LAND_AT_POINT: {
setTask("Landing at point");
if (!getHasTask()) {
setActiveDestination();
std::ostringstream taskSS;
taskSS.precision(10),
taskSS << "{"
<< "id = 'LandAtPoint', "
<< "lat = " << activeDestination.lat << ", "
<< "lng = " << activeDestination.lng
<< "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
break;
}
default:
break;
}

View File

@ -600,6 +600,22 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setOperateAs(operateAs);
}
else if (key.compare("landAtPoint") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
Unit* unit = unitsManager->getGroupLeader(ID);
list<Coords> newPath;
newPath.push_back(loc);
unit->setActivePath(newPath);
unit->setState(State::LAND_AT_POINT);
log(username + " tasked unit " + unit->getName() + " to land at point", true);
}
else if (key.compare("setCommandModeOptions") == 0)
{
setCommandModeOptions(value);