mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Merge pull request #449 from Pax1601/small-issues
Added "land at point" state for helicopters
This commit is contained in:
commit
c26691c2fc
@ -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");
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
61
client/public/themes/olympus/images/icons/land-at-point.svg
Normal file
61
client/public/themes/olympus/images/icons/land-at-point.svg
Normal 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 |
51
client/public/themes/olympus/images/states/land-at-point.svg
Normal file
51
client/public/themes/olympus/images/states/land-at-point.svg
Normal 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 |
@ -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"];
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
*
|
||||
|
||||
@ -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
|
||||
|
||||
@ -68,7 +68,8 @@ namespace State
|
||||
FIRE_AT_AREA,
|
||||
SIMULATE_FIRE_FIGHT,
|
||||
SCENIC_AAA,
|
||||
MISS_ON_PURPOSE
|
||||
MISS_ON_PURPOSE,
|
||||
LAND_AT_POINT
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user