mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Resolved conflicts
This commit is contained in:
commit
7605dd26ff
@ -2,6 +2,7 @@ var express = require('express');
|
||||
var path = require('path');
|
||||
var cookieParser = require('cookie-parser');
|
||||
var logger = require('morgan');
|
||||
var fs = require('fs');
|
||||
|
||||
var atcRouter = require('./routes/api/atc');
|
||||
var indexRouter = require('./routes/index');
|
||||
@ -23,12 +24,14 @@ app.use('/uikit', uikitRouter);
|
||||
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
let rawdata = fs.readFileSync('../olympus.json');
|
||||
let config = JSON.parse(rawdata);
|
||||
app.get('/config', (req, res) => res.send(config));
|
||||
|
||||
module.exports = app;
|
||||
|
||||
const DemoDataGenerator = require('./demo.js');
|
||||
|
||||
var demoDataGenerator = new DemoDataGenerator(10);
|
||||
|
||||
app.get('/demo/units', (req, res) => demoDataGenerator.units(req, res));
|
||||
app.get('/demo/logs', (req, res) => demoDataGenerator.logs(req, res));
|
||||
app.get('/demo/bullseyes', (req, res) => demoDataGenerator.bullseyes(req, res));
|
||||
|
||||
@ -625,6 +625,7 @@ class DemoDataGenerator {
|
||||
|
||||
units(req, res){
|
||||
var ret = this.demoUnits;
|
||||
ret.time = Date.now();
|
||||
res.send(JSON.stringify(ret));
|
||||
};
|
||||
|
||||
|
||||
4
client/package-lock.json
generated
4
client/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "DCSOlympus",
|
||||
"version": "0.1.0-alpha",
|
||||
"version": "0.1.1-alpha",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "DCSOlympus",
|
||||
"version": "0.1.0-alpha",
|
||||
"version": "0.1.1-alpha",
|
||||
"dependencies": {
|
||||
"@types/geojson": "^7946.0.10",
|
||||
"@types/leaflet": "^1.9.0",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "DCSOlympus",
|
||||
"node-main": "./bin/www",
|
||||
"main": "http://localhost:3000",
|
||||
"version": "0.1.0-alpha",
|
||||
"version": "0.1.1-alpha",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"copy": "copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet.css",
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
position: absolute;
|
||||
row-gap: 5px;
|
||||
width: 230px;
|
||||
z-index: 1000;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
#aircraft-spawn-menu {
|
||||
|
||||
@ -77,6 +77,23 @@ form > div {
|
||||
}
|
||||
|
||||
|
||||
.ol-scrollable::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.ol-scrollable::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
.ol-scrollable::-webkit-scrollbar-thumb {
|
||||
background-color: white;
|
||||
border-radius: 100px;
|
||||
opacity: 0.8;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
.ol-panel {
|
||||
background-color: var(--background-steel);
|
||||
border-radius: 15px;
|
||||
@ -146,8 +163,9 @@ form > div {
|
||||
}
|
||||
|
||||
.ol-select>.ol-select-options {
|
||||
position: absolute;
|
||||
border-radius: var( --border-radius-md );
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
max-height: 0;
|
||||
translate: 0 -2px;
|
||||
z-index: 1000;
|
||||
@ -164,9 +182,15 @@ form > div {
|
||||
overflow-y: auto;
|
||||
padding: 8px 0;
|
||||
min-width: 100%;
|
||||
z-index:9999;
|
||||
}
|
||||
|
||||
|
||||
.ol-select.is-open[data-position="top"] > .ol-select-options {
|
||||
top:0;
|
||||
translate:0 -100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.ol-select>.ol-select-options > div {
|
||||
@ -214,22 +238,6 @@ form > div {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.ol-select>.ol-select-options::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.ol-select>.ol-select-options::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
.ol-select>.ol-select-options::-webkit-scrollbar-thumb {
|
||||
background-color: white;
|
||||
border-radius: 100px;
|
||||
opacity: 0.8;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
.ol-panel-list {
|
||||
border-radius: var(--border-radius-sm);
|
||||
@ -663,101 +671,93 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit {
|
||||
}
|
||||
|
||||
#roe-buttons-container button::before, #reaction-to-threat-buttons-container button::before {
|
||||
background-position:center;
|
||||
background-repeat: no-repeat;
|
||||
background-size:16px 16px;
|
||||
content: "";
|
||||
display:block;
|
||||
height:16px;
|
||||
width:16px;
|
||||
height:24px;
|
||||
width:24px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#roe-buttons-container button[title="Free"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_free_light.svg");
|
||||
}
|
||||
|
||||
#roe-buttons-container button[title="Designated free"]::before {
|
||||
#roe-buttons-container button[title="Hold"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg");
|
||||
}
|
||||
|
||||
#roe-buttons-container button[title="Designated"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg");
|
||||
#roe-buttons-container button[title="Hold"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg");
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
#roe-buttons-container button[title="Return"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_defend_light.svg");
|
||||
}
|
||||
|
||||
#roe-buttons-container button[title="Return"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_defend_dark.svg");
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
#roe-buttons-container button[title="Designated"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_target_light.svg");
|
||||
}
|
||||
|
||||
#roe-buttons-container button[title="Hold"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_actions_nothing_light.svg");
|
||||
#roe-buttons-container button[title="Designated"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_target_dark.svg");
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
#roe-buttons-container button[title="Free"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_free_light.svg");
|
||||
}
|
||||
|
||||
#roe-buttons-container button[title="Free"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_free_dark.svg");
|
||||
}
|
||||
|
||||
#roe-buttons-container button[title="Designated free"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg");
|
||||
}
|
||||
|
||||
#roe-buttons-container button[title="Designated"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg");
|
||||
}
|
||||
|
||||
#roe-buttons-container button[title="Return"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_target_dark.svg");
|
||||
}
|
||||
|
||||
#roe-buttons-container button[title="Hold"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_actions_nothing_dark.svg");
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="None"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_actions_nothing_light.svg");
|
||||
background-image: url( "/themes/olympus/images/icons_threat_nothing_light.svg");
|
||||
}
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Passive"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg");
|
||||
}
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Evade"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg");
|
||||
}
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Escape"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_threat_retreat_light.svg");
|
||||
}
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Abort"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg");
|
||||
}
|
||||
#reaction-to-threat-buttons-container button[title="None"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_actions_nothing_light.svg");
|
||||
}
|
||||
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="None"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_actions_nothing_dark.svg");
|
||||
background-image: url( "/themes/olympus/images/icons_threat_nothing_dark.svg");
|
||||
}
|
||||
|
||||
|
||||
/**/
|
||||
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Passive"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_threat_cms_light.svg");
|
||||
}
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Passive"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg");
|
||||
background-image: url( "/themes/olympus/images/icons_threat_cms_dark.svg");
|
||||
}
|
||||
|
||||
|
||||
/**/
|
||||
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Evade"]::before {
|
||||
background-image: url( "/themes/olympus/images/icons_threat_defend_light.svg");
|
||||
}
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Evade"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg");
|
||||
background-image: url( "/themes/olympus/images/icons_threat_defend_dark.svg");
|
||||
}
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Escape"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_threat_retreat_dark.svg");
|
||||
}
|
||||
|
||||
#reaction-to-threat-buttons-container button[title="Abort"].selected::before {
|
||||
background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg");
|
||||
}
|
||||
/****************************************************************************************/
|
||||
|
||||
|
||||
#splash-screen {
|
||||
|
||||
@ -12,11 +12,17 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#unit-control-panel h3 {
|
||||
margin-bottom:8px;
|
||||
}
|
||||
|
||||
#unit-control-panel #selected-units-container {
|
||||
align-items: left;
|
||||
border-radius: var( --border-radius-md );
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
max-height: 136px;
|
||||
overflow-y:auto;
|
||||
row-gap: 4px;
|
||||
}
|
||||
|
||||
@ -85,5 +91,10 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
|
||||
|
||||
#unit-control-panel h4 {
|
||||
margin-bottom:8px;
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
|
||||
#unit-control-panel #threat,
|
||||
#unit-control-panel #roe {
|
||||
margin-top:12px;
|
||||
}
|
||||
@ -58,7 +58,6 @@
|
||||
display:flex;
|
||||
flex-flow: column nowrap;
|
||||
row-gap: 8px;
|
||||
text-align: center;
|
||||
width:45%;
|
||||
}
|
||||
|
||||
@ -67,23 +66,23 @@
|
||||
align-items: center;
|
||||
column-gap: 8px;
|
||||
display:flex;
|
||||
justify-content: flex-end;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#loadout-items > *::before {
|
||||
align-items: center;
|
||||
background-color: var( --secondary-light-grey );
|
||||
border-radius: 50%;
|
||||
border-radius: var( --border-radius-sm );
|
||||
content: attr( data-qty );
|
||||
display:flex;
|
||||
font-weight: var( --font-weight-bolder );
|
||||
justify-content: center;
|
||||
height:20px;
|
||||
width:20px;
|
||||
padding:1px 4px;
|
||||
}
|
||||
|
||||
#loadout-items > *::after {
|
||||
content: attr( data-item );
|
||||
width:52px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -8,36 +8,61 @@ export class Dropdown {
|
||||
|
||||
constructor(ID: string, callback: CallableFunction, options: string[] | null = null)
|
||||
{
|
||||
this.#element = <HTMLElement>document.getElementById(ID);
|
||||
this.#options = <HTMLElement>this.#element.querySelector(".ol-select-options");
|
||||
this.#value = <HTMLElement>this.#element.querySelector(".ol-select-value");
|
||||
this.#element = <HTMLElement>document.getElementById(ID);
|
||||
this.#options = <HTMLElement>this.#element.querySelector(".ol-select-options");
|
||||
this.#value = <HTMLElement>this.#element.querySelector(".ol-select-value");
|
||||
this.#defaultValue = this.#value.innerText;
|
||||
this.#callback = callback;
|
||||
this.#callback = callback;
|
||||
|
||||
if (options != null) {
|
||||
this.setOptions(options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Do open/close toggle
|
||||
this.#element.addEventListener("click", ev => {
|
||||
|
||||
if ( ev.target instanceof HTMLElement && ev.target.nodeName !== "A" ) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
this.#value.addEventListener( "click", ev => {
|
||||
|
||||
ev.stopPropagation();
|
||||
this.#element.classList.toggle("is-open");
|
||||
this.#element.classList.toggle( "is-open" );
|
||||
this.#clip();
|
||||
|
||||
});
|
||||
|
||||
// Autoclose on mouseleave
|
||||
this.#element.addEventListener("mouseleave", ev => {
|
||||
this.#element.classList.remove("is-open");
|
||||
this.#close();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
#clip() {
|
||||
|
||||
const options = this.#options;
|
||||
const bounds = options.getBoundingClientRect();
|
||||
|
||||
this.#element.dataset.position = ( bounds.bottom > window.innerHeight ) ? "top" : "";
|
||||
|
||||
}
|
||||
|
||||
|
||||
#close() {
|
||||
this.#element.classList.remove( "is-open" );
|
||||
this.#element.dataset.position = "";
|
||||
}
|
||||
|
||||
|
||||
#open() {
|
||||
this.#element.classList.add( "is-open" );
|
||||
}
|
||||
|
||||
|
||||
#toggle() {
|
||||
|
||||
if ( this.#element.classList.contains( "is-open" ) ) {
|
||||
this.#close();
|
||||
} else {
|
||||
this.#open();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
setOptions(optionsList: string[])
|
||||
{
|
||||
this.#optionsList = optionsList;
|
||||
@ -47,7 +72,9 @@ export class Dropdown {
|
||||
button.textContent = option;
|
||||
div.appendChild(button);
|
||||
button.addEventListener("click", (e: MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
this.#value.innerText = option;
|
||||
this.#close();
|
||||
this.#callback( option, e );
|
||||
});
|
||||
return div;
|
||||
|
||||
@ -168,7 +168,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
/********* Ground unit spawn menu *********/
|
||||
#setGroundUnitRole(role: string) {
|
||||
this.#spawnOptions.role = role;
|
||||
this.#resetGroundUnitRole();
|
||||
this.#resetGroundUnitType();
|
||||
this.#groundUnitTypeDropdown.setOptions(groundUnitsDatabase.getByRole(role).map((blueprint) => { return blueprint.label }));
|
||||
this.#groundUnitTypeDropdown.selectValue(0);
|
||||
this.clip();
|
||||
|
||||
@ -75,7 +75,7 @@ export class Slider {
|
||||
{
|
||||
this.#value = newValue;
|
||||
if (this.#slider != null)
|
||||
this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * 100);
|
||||
this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * parseFloat(this.#slider.max));
|
||||
this.#onValue()
|
||||
}
|
||||
}
|
||||
@ -120,7 +120,7 @@ export class Slider {
|
||||
this.#dragged = false;
|
||||
if (this.#slider != null)
|
||||
{
|
||||
this.#value = this.#minValue + parseFloat(this.#slider.value) / 100 * (this.#maxValue - this.#minValue);
|
||||
this.#value = this.#minValue + parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue);
|
||||
this.#callback(this.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,8 +9,9 @@ import { AIC } from "./aic/aic";
|
||||
import { ATC } from "./atc/atc";
|
||||
import { FeatureSwitches } from "./featureswitches";
|
||||
import { LogPanel } from "./panels/logpanel";
|
||||
import { getAirbases, getBullseye as getBullseyes, getMission, getUnits, toggleDemoEnabled } from "./server/server";
|
||||
import { getAirbases, getBullseye as getBullseyes, getConfig, getMission, getUnits, setAddress, toggleDemoEnabled } from "./server/server";
|
||||
import { UnitDataTable } from "./units/unitdatatable";
|
||||
import { keyEventWasInInput } from "./other/utils";
|
||||
|
||||
var map: Map;
|
||||
|
||||
@ -69,16 +70,33 @@ function setup() {
|
||||
/* Setup event handlers */
|
||||
setupEvents();
|
||||
|
||||
/* On the first connection, force request of full data */
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseyes((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => {getMissionData()?.update(data)});
|
||||
getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */);
|
||||
|
||||
/* Start periodically requesting updates */
|
||||
startPeriodicUpdate();
|
||||
getConfig(readConfig)
|
||||
}
|
||||
|
||||
function readConfig(config: any)
|
||||
{
|
||||
if (config && config["server"] != undefined && config["server"]["address"] != undefined && config["server"]["port"] != undefined)
|
||||
{
|
||||
const address = config["server"]["address"];
|
||||
const port = config["server"]["port"];
|
||||
if ((typeof address === 'string' || address instanceof String) && typeof port == 'number')
|
||||
{
|
||||
setAddress(window.location.hostname, <number>port);
|
||||
}
|
||||
|
||||
/* On the first connection, force request of full data */
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseyes((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => {getMissionData()?.update(data)});
|
||||
getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */);
|
||||
|
||||
/* Start periodically requesting updates */
|
||||
startPeriodicUpdate();
|
||||
}
|
||||
else {
|
||||
throw new Error('Could not read configuration file!');
|
||||
}
|
||||
}
|
||||
|
||||
function startPeriodicUpdate() {
|
||||
requestUpdate();
|
||||
@ -124,14 +142,16 @@ function checkSessionHash(newSessionHash: string) {
|
||||
function setupEvents() {
|
||||
/* Generic clicks */
|
||||
document.addEventListener("click", (ev) => {
|
||||
|
||||
if (ev instanceof PointerEvent && ev.target instanceof HTMLElement) {
|
||||
if (ev instanceof MouseEvent && ev.target instanceof HTMLElement) {
|
||||
|
||||
const target = ev.target;
|
||||
|
||||
if (target.classList.contains("olympus-dialog-close")) {
|
||||
target.closest("div.olympus-dialog")?.classList.add("hide");
|
||||
}
|
||||
|
||||
const triggerElement = target.closest("[data-on-click]");
|
||||
|
||||
if (triggerElement instanceof HTMLElement) {
|
||||
const eventName: string = triggerElement.dataset.onClick || "";
|
||||
let params = JSON.parse(triggerElement.dataset.onClickParams || "{}");
|
||||
@ -148,23 +168,22 @@ function setupEvents() {
|
||||
|
||||
/* Keyup events */
|
||||
document.addEventListener("keyup", ev => {
|
||||
|
||||
if ( keyEventWasInInput( ev ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ev.code) {
|
||||
|
||||
case "KeyL":
|
||||
document.body.toggleAttribute("data-hide-labels");
|
||||
break;
|
||||
|
||||
case "KeyD":
|
||||
toggleDemoEnabled();
|
||||
break;
|
||||
|
||||
case "Minus": // For Veltro's italian layout keyboard, which lacks a quote
|
||||
case "Quote":
|
||||
unitDataTable.toggle();
|
||||
break
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
@ -26,6 +26,27 @@ export function ConvertDDToDMS(D: number, lng: boolean) {
|
||||
}
|
||||
|
||||
|
||||
export function dataPointMap( container:HTMLElement, data:any) {
|
||||
|
||||
Object.keys( data ).forEach( ( key ) => {
|
||||
|
||||
const val = "" + data[ key ]; // Ensure a string
|
||||
|
||||
container.querySelectorAll( `[data-point="${key}"]`).forEach( el => {
|
||||
|
||||
// We could probably have options here
|
||||
if ( el instanceof HTMLInputElement ) {
|
||||
el.value = val;
|
||||
} else if ( el instanceof HTMLElement ) {
|
||||
el.innerText = val;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function deg2rad(deg: number) {
|
||||
var pi = Math.PI;
|
||||
return deg * (pi / 180);
|
||||
@ -48,6 +69,15 @@ export function distance(lat1: number, lon1: number, lat2: number, lon2: number)
|
||||
}
|
||||
|
||||
|
||||
export function keyEventWasInInput( event:KeyboardEvent ) {
|
||||
|
||||
const target = event.target;
|
||||
|
||||
return ( target instanceof HTMLElement && ( [ "INPUT", "TEXTAREA" ].includes( target.nodeName ) ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function rad2deg(rad: number) {
|
||||
var pi = Math.PI;
|
||||
return rad / (pi / 180);
|
||||
|
||||
@ -36,10 +36,17 @@ export class MouseInfoPanel extends Panel {
|
||||
var el = <HTMLElement>this.getElement().querySelector(`#bullseye-${idx}`);
|
||||
|
||||
if ( el != null ) {
|
||||
|
||||
var dist = distance(bullseyes[idx].latitude, bullseyes[idx].longitude, mousePosition.lat, mousePosition.lng);
|
||||
var bear = bearing(bullseyes[idx].latitude, bullseyes[idx].longitude, mousePosition.lat, mousePosition.lng);
|
||||
|
||||
el.dataset.bearing = zeroAppend(Math.floor(bear), 3);
|
||||
let bng = zeroAppend(Math.floor(bear), 3);
|
||||
|
||||
if ( bng === "000" ) {
|
||||
bng = "360";
|
||||
}
|
||||
|
||||
el.dataset.bearing = bng;
|
||||
el.dataset.distance = zeroAppend(Math.floor(dist*0.000539957), 3);
|
||||
el.dataset.distanceUnits = "NM";
|
||||
}
|
||||
|
||||
@ -11,9 +11,13 @@ export class Panel {
|
||||
this.#visible = true;
|
||||
}
|
||||
|
||||
protected onHide() {}
|
||||
|
||||
hide() {
|
||||
this.#element.classList.toggle("hide", true);
|
||||
this.#visible = false;
|
||||
|
||||
this.onHide();
|
||||
}
|
||||
|
||||
toggle() {
|
||||
|
||||
@ -1,14 +1,18 @@
|
||||
import { getUnitsManager } from "..";
|
||||
import { Slider } from "../controls/slider";
|
||||
import { dataPointMap } from "../other/utils";
|
||||
import { aircraftDatabase } from "../units/aircraftdatabase";
|
||||
import { groundUnitsDatabase } from "../units/groundunitsdatabase";
|
||||
import { Aircraft, GroundUnit, Unit } from "../units/unit";
|
||||
import { UnitDatabase } from "../units/unitdatabase";
|
||||
import { UnitsManager } from "../units/unitsmanager";
|
||||
import { Panel } from "./panel";
|
||||
|
||||
const ROEs: string[] = ["Free", "Designated free", "Designated", "Return", "Hold"];
|
||||
const reactionsToThreat: string[] = ["None", "Passive", "Evade", "Escape", "Abort"];
|
||||
// const ROEs: string[] = ["Free", "Designated free", "Designated", "Return", "Hold"]; // Full list
|
||||
// const reactionsToThreat: string[] = ["None", "Passive", "Evade", "Escape", "Abort"]; // Full list
|
||||
|
||||
const ROEs: string[] = [ "Hold", "Return", "Designated", "Free" ];
|
||||
const reactionsToThreat: string[] = [ "None", "Passive", "Evade" ];
|
||||
|
||||
const minSpeedValues: { [key: string]: number } = { Aircraft: 100, Helicopter: 0, NavyUnit: 0, GroundUnit: 0 };
|
||||
const maxSpeedValues: { [key: string]: number } = { Aircraft: 800, Helicopter: 300, NavyUnit: 60, GroundUnit: 60 };
|
||||
const speedIncrements: { [key: string]: number } = { Aircraft: 25, Helicopter: 10, NavyUnit: 5, GroundUnit: 5 };
|
||||
@ -19,14 +23,23 @@ const altitudeIncrements: { [key: string]: number } = { Aircraft: 2500, Helicopt
|
||||
export class UnitControlPanel extends Panel {
|
||||
#altitudeSlider: Slider;
|
||||
#airspeedSlider: Slider;
|
||||
#expectedAltitude:number = -1;
|
||||
#expectedSpeed: number = -1;
|
||||
#optionButtons: { [key: string]: HTMLButtonElement[] } = {}
|
||||
|
||||
constructor(ID: string) {
|
||||
super(ID);
|
||||
|
||||
/* Unit control sliders */
|
||||
this.#altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => getUnitsManager().selectedUnitsSetAltitude(value * 0.3048));
|
||||
this.#airspeedSlider = new Slider("airspeed-slider", 0, 100, "kts", (value: number) => getUnitsManager().selectedUnitsSetSpeed(value / 1.94384));
|
||||
this.#altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => {
|
||||
this.#expectedAltitude = value;
|
||||
getUnitsManager().selectedUnitsSetAltitude(value * 0.3048)
|
||||
});
|
||||
|
||||
this.#airspeedSlider = new Slider("airspeed-slider", 0, 100, "kts", (value: number) => {
|
||||
this.#expectedSpeed = value;
|
||||
getUnitsManager().selectedUnitsSetSpeed(value / 1.94384)
|
||||
});
|
||||
|
||||
/* Option buttons */
|
||||
this.#optionButtons["ROE"] = ROEs.map((option: string, index: number) => {
|
||||
@ -55,6 +68,39 @@ export class UnitControlPanel extends Panel {
|
||||
this.hide();
|
||||
}
|
||||
|
||||
|
||||
// Do this after panel is hidden (make sure there's a reset)
|
||||
protected onHide() {
|
||||
this.#expectedAltitude = -1;
|
||||
this.#expectedSpeed = -1;
|
||||
}
|
||||
|
||||
|
||||
// Update function will only be allowed to update the sliders once it's matched the expected value for the first time (due to lag of Ajax request)
|
||||
#updateCanSetAltitudeSlider( altitude:number ) {
|
||||
|
||||
if ( this.#expectedAltitude < 0 || altitude === this.#expectedAltitude ) {
|
||||
this.#expectedAltitude = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#updateCanSetSpeedSlider( altitude:number ) {
|
||||
|
||||
if ( this.#expectedSpeed < 0 || altitude === this.#expectedSpeed ) {
|
||||
this.#expectedSpeed = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
update() {
|
||||
var units = getUnitsManager().getSelectedUnits();
|
||||
if (this.getElement() != null && units.length > 0) {
|
||||
@ -69,23 +115,13 @@ export class UnitControlPanel extends Panel {
|
||||
else
|
||||
database = null; // TODO add databases for other unit types
|
||||
|
||||
if (index === 0) {
|
||||
this.getElement().querySelectorAll(`[data-object|="unit"]`).forEach(marker => {
|
||||
marker.setAttribute("data-coalition", unit.getMissionData().coalition);
|
||||
const shortLabel = <HTMLElement>marker.querySelector(".unit-short-label");
|
||||
if (shortLabel)
|
||||
shortLabel.innerText = database?.getByName(unit.getBaseData().name)?.shortLabel || "";
|
||||
});
|
||||
}
|
||||
console.log( unit.getBaseData() );
|
||||
|
||||
var button = document.createElement("button");
|
||||
const unitName = <HTMLInputElement>this.getElement().querySelector("#unit-name");
|
||||
var callsign = aircraftDatabase.getByName(unit.getBaseData().unitName)?.label || "";
|
||||
var callsign = unit.getBaseData().unitName || "";
|
||||
|
||||
button.innerText = "";
|
||||
button.setAttribute("data-short-label", database?.getByName(unit.getBaseData().name)?.shortLabel || "");
|
||||
button.setAttribute("data-callsign", callsign);
|
||||
unitName.value = callsign;
|
||||
|
||||
button.setAttribute("data-coalition", unit.getMissionData().coalition);
|
||||
button.classList.add("pill", "highlight-coalition")
|
||||
@ -104,6 +140,7 @@ export class UnitControlPanel extends Panel {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#showFlightControlSliders(units: Unit[])
|
||||
{
|
||||
if (getUnitsManager().getSelectedUnitsType() !== undefined)
|
||||
@ -132,12 +169,24 @@ export class UnitControlPanel extends Panel {
|
||||
this.#altitudeSlider.setIncrement(altitudeIncrements[unitsType]);
|
||||
|
||||
this.#airspeedSlider.setActive(targetSpeed != undefined);
|
||||
if (targetSpeed != undefined)
|
||||
this.#airspeedSlider.setValue(targetSpeed * 1.94384);
|
||||
if (targetSpeed != undefined) {
|
||||
|
||||
targetSpeed *= 1.94384;
|
||||
|
||||
if ( this.#updateCanSetSpeedSlider( targetSpeed ) ) {
|
||||
this.#airspeedSlider.setValue( targetSpeed );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.#altitudeSlider.setActive(targetAltitude != undefined);
|
||||
if (targetAltitude != undefined)
|
||||
this.#altitudeSlider.setValue(targetAltitude / 0.3048);
|
||||
if (targetAltitude != undefined) {
|
||||
targetAltitude /= 0.3048;
|
||||
|
||||
if ( this.#updateCanSetAltitudeSlider( targetAltitude ) ) {
|
||||
this.#altitudeSlider.setValue( targetAltitude );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.#airspeedSlider.setActive(false);
|
||||
|
||||
@ -2,9 +2,8 @@ import * as L from 'leaflet'
|
||||
import { setConnected } from '..';
|
||||
import { SpawnOptions } from '../controls/mapcontextmenu';
|
||||
|
||||
/* Edit here to change server address */
|
||||
const REST_ADDRESS = "http://localhost:30000/olympus";
|
||||
const DEMO_ADDRESS = "http://localhost:3000/demo";
|
||||
var REST_ADDRESS = "http://localhost:30000/olympus";
|
||||
var DEMO_ADDRESS = window.location.href + "demo";
|
||||
const UNITS_URI = "units";
|
||||
const LOGS_URI = "logs";
|
||||
const AIRBASES_URI = "airbases";
|
||||
@ -24,9 +23,14 @@ export function GET(callback: CallableFunction, uri: string){
|
||||
xmlHttp.open("GET", `${demoEnabled? DEMO_ADDRESS: REST_ADDRESS}/${uri}`, true);
|
||||
xmlHttp.onload = function (e) {
|
||||
var data = JSON.parse(xmlHttp.responseText);
|
||||
callback(data);
|
||||
lastUpdateTime = parseInt(data.time);
|
||||
setConnected(true);
|
||||
if (parseInt(data.time) > lastUpdateTime)
|
||||
{
|
||||
callback(data);
|
||||
lastUpdateTime = parseInt(data.time);
|
||||
if (isNaN(lastUpdateTime))
|
||||
lastUpdateTime = 0;
|
||||
setConnected(true);
|
||||
}
|
||||
};
|
||||
xmlHttp.onerror = function () {
|
||||
console.error("An error occurred during the XMLHttpRequest");
|
||||
@ -45,6 +49,24 @@ export function POST(request: object, callback: CallableFunction){
|
||||
xhr.send(JSON.stringify(request));
|
||||
}
|
||||
|
||||
export function getConfig(callback: CallableFunction) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("GET", window.location.href + "config", true);
|
||||
xmlHttp.onload = function (e) {
|
||||
var data = JSON.parse(xmlHttp.responseText);
|
||||
callback(data);
|
||||
};
|
||||
xmlHttp.onerror = function () {
|
||||
console.error("An error occurred during the XMLHttpRequest, could not retrieve configuration file");
|
||||
};
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
||||
export function setAddress(address: string, port: number) {
|
||||
REST_ADDRESS = `http://${address}:${port}/olympus`
|
||||
console.log(`Setting REST address to ${REST_ADDRESS}`)
|
||||
}
|
||||
|
||||
export function getAirbases(callback: CallableFunction) {
|
||||
GET(callback, AIRBASES_URI);
|
||||
}
|
||||
|
||||
@ -573,6 +573,15 @@ export class GroundUnit extends Unit {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
getMarkerHTML() {
|
||||
var role = groundUnitsDatabase.getByName(this.getBaseData().name)?.loadouts[0].roles[0];
|
||||
return `<div class="unit" data-object="unit-${this.getMarkerCategory()}" data-coalition="${this.getMissionData().coalition}">
|
||||
<div class="unit-selected-spotlight"></div>
|
||||
<div class="unit-marker"></div>
|
||||
<div class="unit-short-label">${role?.substring(0, 1)?.toUpperCase() || ""}</div>
|
||||
</div>`
|
||||
}
|
||||
|
||||
getMarkerCategory()
|
||||
{
|
||||
// TODO this is very messy
|
||||
|
||||
@ -3,11 +3,13 @@ import { getMap, getUnitDataTable } from "..";
|
||||
import { Unit } from "./unit";
|
||||
import { cloneUnit } from "../server/server";
|
||||
import { IDLE, MOVE_UNIT } from "../map/map";
|
||||
import { keyEventWasInInput } from "../other/utils";
|
||||
|
||||
export class UnitsManager {
|
||||
#units: { [ID: number]: Unit };
|
||||
#copiedUnits: Unit[];
|
||||
#selectionEventDisabled: boolean = false;
|
||||
#pasteDisabled: boolean = false;
|
||||
|
||||
constructor() {
|
||||
this.#units = {};
|
||||
@ -330,16 +332,21 @@ export class UnitsManager {
|
||||
|
||||
pasteUnits()
|
||||
{
|
||||
for (let idx in this.#copiedUnits)
|
||||
if (!this.#pasteDisabled)
|
||||
{
|
||||
var unit = this.#copiedUnits[idx];
|
||||
cloneUnit(unit.ID, getMap().getMouseCoordinates());
|
||||
for (let idx in this.#copiedUnits)
|
||||
{
|
||||
var unit = this.#copiedUnits[idx];
|
||||
cloneUnit(unit.ID, getMap().getMouseCoordinates());
|
||||
}
|
||||
this.#pasteDisabled = true;
|
||||
setTimeout(() => this.#pasteDisabled = false, 250);
|
||||
}
|
||||
}
|
||||
|
||||
#onKeyDown(event: KeyboardEvent)
|
||||
{
|
||||
if (event.key === "Delete")
|
||||
if ( !keyEventWasInInput( event ) && event.key === "Delete")
|
||||
{
|
||||
this.selectedUnitsDelete();
|
||||
}
|
||||
|
||||
@ -10,13 +10,13 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;600;700;800&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z4L2TC3YX0"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-Z4L2TC3YX0');
|
||||
</script>
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-Z4L2TC3YX0"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-Z4L2TC3YX0');
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<div class="ol-select-options">
|
||||
<div id="olympus-toolbar-summary">
|
||||
<h3>Olympus</h3>
|
||||
<div class="accent-green app-version-number">v0.1.0</div>
|
||||
<div class="accent-green app-version-number">v0.1.1</div>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://www.discord.com" target="_blank">Discord</a>
|
||||
|
||||
@ -982,6 +982,42 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="example">
|
||||
|
||||
<div class="ol-select">
|
||||
<div class="ol-select-value">
|
||||
The selected value goes here
|
||||
</div>
|
||||
<div class="ol-select-options">
|
||||
<div>
|
||||
<button>Option 1</button>
|
||||
</div>
|
||||
<div>
|
||||
<button>Option 2</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="example">
|
||||
|
||||
<div class="ol-select" data-position="top">
|
||||
<div class="ol-select-value">
|
||||
Options go up
|
||||
</div>
|
||||
<div class="ol-select-options">
|
||||
<div>
|
||||
<button>Option 1</button>
|
||||
</div>
|
||||
<div>
|
||||
<button>Option 2</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -991,7 +1027,7 @@
|
||||
<div class="content-body">
|
||||
<div class="example">
|
||||
|
||||
<div id="airbase-contextmenu" class="ol-panel">
|
||||
<div id="airbase-contextmenu" class="ol-panel" style="position:relative;">
|
||||
<h3 id="airbase-name">Al Alhambra</h3>
|
||||
<dl id="airbase-properties" class="ol-data-grid">
|
||||
<dt>Runway 1</dt>
|
||||
@ -1048,6 +1084,46 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div id="fuel-percentage" data-percentage="45"></div>
|
||||
<div id="fuel-display">
|
||||
<div id="fuel-bar" class="highlight-coalition" data-coalition="blue" style="width:0%;"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="example">
|
||||
|
||||
<div id="unit-info-panel" class="ol-panel" style="position:relative;">
|
||||
|
||||
<div class="ol-panel-board">
|
||||
|
||||
<div id="general" class="panel-section">
|
||||
<h3 class="unit-name">Olympus 1-1</h3>
|
||||
<div class="ol-group">
|
||||
<div class="unit-label">Name</div>
|
||||
<div class="unit-control">AI Controlled</div>
|
||||
</div>
|
||||
<div id="current-task" class="pill highlight-coalition" data-coalition="blue" data-current-task="Awaiting tasking"></div>
|
||||
</div>
|
||||
|
||||
<div id="loadout-container" class="panel-section">
|
||||
|
||||
<div id="loadout">
|
||||
<div id="loadout-silhouette" style="--loadout-background-image:url('/images/units/f-15.png');"></div>
|
||||
<div id="loadout-items">
|
||||
<div data-qty="1150" data-item="30mm AP"></div>
|
||||
<div data-qty="2" data-item="AIM-9M"></div>
|
||||
<div data-qty="6" data-item="Mk-82"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="fuel-percentage" data-percentage="45"></div>
|
||||
<div id="fuel-display">
|
||||
<div id="fuel-bar" class="highlight-coalition" data-coalition="blue" style="width:0%;"></div>
|
||||
|
||||
@ -1,23 +1,16 @@
|
||||
<div id="unit-control-panel" class="ol-panel ol-panel-padding-lg">
|
||||
|
||||
<h3>Selected Units</h3>
|
||||
|
||||
<div id="unit-selection">
|
||||
|
||||
<div id="unit-identification">
|
||||
<div data-object="unit-aircraft">
|
||||
<div class="unit-marker"></div>
|
||||
<div class="unit-short-label"></div>
|
||||
</div>
|
||||
|
||||
<input id="unit-name" value="" readonly disabled />
|
||||
|
||||
<!-- <button id="edit-unit-name" data-on-click="editUnitName"></button> -->
|
||||
</div>
|
||||
|
||||
<div id="selected-units-container" class="ol-scroll">
|
||||
<div id="selected-units-container" class="ol-scrollable">
|
||||
<!-- This is where all the unit selection buttons will be shown-->
|
||||
<!-- <button class="pill highlight-coalition" data-coalition="blue" data-short-label="18">Olympus 1-1</button> -->
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div id="flight-data">
|
||||
<h4>Flight controls</h4>
|
||||
<div class="slider-container flight-control-slider" id="airspeed-slider">
|
||||
@ -52,9 +45,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4>Reaction to threat</h4>
|
||||
<div id="reaction-to-threat-buttons-container" class="ol-group ol-button-box">
|
||||
<!-- This is where the reaction to threat buttons will be shown -->
|
||||
<div id="threat">
|
||||
<h4>Reaction to threat</h4>
|
||||
<div id="reaction-to-threat-buttons-container" class="ol-group ol-button-box">
|
||||
<!-- This is where the reaction to threat buttons will be shown -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
BIN
img/olympus.ico
Normal file
BIN
img/olympus.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@ -1,23 +1,25 @@
|
||||
#define nwjsFolder "C:\Users\dpass\Documents\nwjs\"
|
||||
#define version "v0.1.1-alpha"
|
||||
|
||||
[Setup]
|
||||
AppName=DCS Olympus
|
||||
AppVerName=DCS Olympus Alpha v0.1.1
|
||||
AppVerName={#version}
|
||||
DefaultDirName={usersavedgames}\DCS.openbeta
|
||||
DefaultGroupName=DCSOlympus
|
||||
OutputBaseFilename=DCSOlympus
|
||||
OutputBaseFilename=DCSOlympus_{#version}
|
||||
UninstallFilesDir={app}\Mods\Services\Olympus
|
||||
;SetupIconFile="..\img\olympus.ico"
|
||||
|
||||
[Tasks]
|
||||
; NOTE: The following entry contains English phrases ("Create a desktop icon" and "Additional icons"). You are free to translate them into another language if required.
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
|
||||
[Files]
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
;Source: "..\scripts\OlympusExport.lua"; DestDir: "{app}\Scripts"; Flags: ignoreversion
|
||||
;Source: "..\scripts\OlympusPatcher.exe"; DestDir: "{app}\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\OlympusHook.lua"; DestDir: "{app}\Scripts\Hooks"; Flags: ignoreversion
|
||||
Source: "..\olympus.json"; DestDir: "{app}\Mods\Services\Olympus"; Flags: onlyifdoesntexist
|
||||
Source: "..\scripts\OlympusCommand.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
Source: "..\scripts\unitPayloads.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
;Source: "..\scripts\OlympusMission.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
|
||||
@ -30,6 +32,7 @@ Source: "..\client\public\*"; DestDir: "{app}\Mods\Services\Olympus\client\publi
|
||||
Source: "..\client\routes\*"; DestDir: "{app}\Mods\Services\Olympus\client\routes"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\views\*"; DestDir: "{app}\Mods\Services\Olympus\client\views"; Flags: ignoreversion recursesubdirs;
|
||||
Source: "..\client\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
|
||||
Source: "..\img\olympus.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
|
||||
Source: "{#nwjsFolder}\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion recursesubdirs;
|
||||
|
||||
[Code]
|
||||
@ -58,7 +61,7 @@ Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; Value
|
||||
ChangesEnvironment=yes
|
||||
|
||||
[Icons]
|
||||
Name: "{userdesktop}\DCS Olympus Client"; Filename: "{app}\Mods\Services\Olympus\client\nw.exe"; Tasks: desktopicon
|
||||
Name: "{userdesktop}\DCS Olympus Client"; Filename: "{app}\Mods\Services\Olympus\client\nw.exe"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus.ico"
|
||||
|
||||
;[Run]
|
||||
;Filename: "{app}\Scripts\OlympusPatcher.exe"; Parameters: "-i"
|
||||
|
||||
@ -15,7 +15,7 @@ declare_plugin(self_ID,
|
||||
shortName = "Olympus",
|
||||
fileMenuName = "Olympus",
|
||||
|
||||
version = "0.1.0-alpha",
|
||||
version = "0.1.1-alpha",
|
||||
state = "installed",
|
||||
developerName= "DCS Refugees 767 squadron",
|
||||
info = _("DCS Olympus is a mod for DCS World. It allows users to spawn, control, task, group, and remove units from a DCS World server using a real-time map interface, similarly to Real Time Strategy games. The user interface also provides useful informations units, like loadouts, fuel, tasking, and so on. In the future, more features for DCS World GCI and JTAC will be available."),
|
||||
|
||||
6
olympus.json
Normal file
6
olympus.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"server": {
|
||||
"address": "localhost",
|
||||
"port": 30000
|
||||
}
|
||||
}
|
||||
@ -341,8 +341,13 @@ function Olympus.delete(ID, lat, lng)
|
||||
Olympus.debug("Olympus.delete " .. ID, 2)
|
||||
local unit = Olympus.getUnitByID(ID)
|
||||
if unit then
|
||||
unit:destroy();
|
||||
Olympus.debug("Olympus.delete completed successfully", 2)
|
||||
if unit:getPlayerName() then
|
||||
trigger.action.explosion(unit:getPoint() , 250 ) --consider replacing with forcibly deslotting the player, however this will work for now
|
||||
Olympus.debug("Olympus.delete completed successfully", 2)
|
||||
else
|
||||
unit:destroy(); --works for AI units not players
|
||||
Olympus.debug("Olympus.delete completed successfully", 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -436,40 +441,42 @@ function Olympus.setMissionData(arg, time)
|
||||
local startIndex = Olympus.groupIndex
|
||||
local endIndex = startIndex + Olympus.groupStep
|
||||
local index = 0
|
||||
for groupName, gp in pairs(mist.DBs.groupsByName) do
|
||||
index = index + 1
|
||||
if index > startIndex then
|
||||
if groupName ~= nil then
|
||||
local group = Group.getByName(groupName)
|
||||
if group ~= nil then
|
||||
local controller = group:getController()
|
||||
for index, unit in pairs(group:getUnits()) do
|
||||
local table = {}
|
||||
table["targets"] = {}
|
||||
table["targets"]["visual"] = controller:getDetectedTargets(1)
|
||||
table["targets"]["radar"] = controller:getDetectedTargets(4)
|
||||
table["targets"]["rwr"] = controller:getDetectedTargets(16)
|
||||
table["targets"]["other"] = controller:getDetectedTargets(2, 8, 32)
|
||||
if mist ~= nil and mist.DBs ~= nil and mist.DBs.groupsByName ~= nil then
|
||||
for groupName, gp in pairs(mist.DBs.groupsByName) do
|
||||
index = index + 1
|
||||
if index > startIndex then
|
||||
if groupName ~= nil then
|
||||
local group = Group.getByName(groupName)
|
||||
if group ~= nil then
|
||||
local controller = group:getController()
|
||||
for index, unit in pairs(group:getUnits()) do
|
||||
local table = {}
|
||||
table["targets"] = {}
|
||||
table["targets"]["visual"] = controller:getDetectedTargets(1)
|
||||
table["targets"]["radar"] = controller:getDetectedTargets(4)
|
||||
table["targets"]["rwr"] = controller:getDetectedTargets(16)
|
||||
table["targets"]["other"] = controller:getDetectedTargets(2, 8, 32)
|
||||
|
||||
table["hasTask"] = controller:hasTask()
|
||||
|
||||
table["ammo"] = unit:getAmmo()
|
||||
table["fuel"] = unit:getFuel()
|
||||
table["life"] = unit:getLife() / unit:getLife0()
|
||||
unitsData[unit:getObjectID()] = table
|
||||
table["hasTask"] = controller:hasTask()
|
||||
|
||||
table["ammo"] = unit:getAmmo()
|
||||
table["fuel"] = unit:getFuel()
|
||||
table["life"] = unit:getLife() / unit:getLife0()
|
||||
unitsData[unit:getObjectID()] = table
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if index >= endIndex then
|
||||
break
|
||||
end
|
||||
end
|
||||
if index >= endIndex then
|
||||
break
|
||||
if index ~= endIndex then
|
||||
Olympus.groupIndex = 0
|
||||
else
|
||||
Olympus.groupIndex = endIndex
|
||||
end
|
||||
end
|
||||
if index ~= endIndex then
|
||||
Olympus.groupIndex = 0
|
||||
else
|
||||
Olympus.groupIndex = endIndex
|
||||
end
|
||||
|
||||
-- Airbases data
|
||||
local base = world.getAirbases()
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
local version = 'v0.1.0-alpha'
|
||||
|
||||
Olympus = {}
|
||||
Olympus.OlympusDLL = nil
|
||||
Olympus.cppRESTDLL = nil
|
||||
Olympus.DLLsloaded = false
|
||||
Olympus.OlympusModPath = os.getenv('DCSOLYMPUS_PATH')..'\\bin\\'
|
||||
|
||||
log.write('Olympus.EXPORT.LUA', log.INFO, 'Executing OlympusExport.lua')
|
||||
|
||||
function Olympus.loadDLLs()
|
||||
-- Add the .dll paths
|
||||
package.cpath = package.cpath..';'..Olympus.OlympusModPath..'?.dll;'
|
||||
|
||||
local status
|
||||
log.write('Olympus.HOOKS.LUA', log.INFO, 'Loading olympus.dll from ['..Olympus.OlympusModPath..']')
|
||||
status, Olympus.OlympusDLL = pcall(require, 'olympus')
|
||||
if status then
|
||||
log.write('Olympus.HOOKS.LUA', log.INFO, 'olympus.dll loaded successfully')
|
||||
return true
|
||||
else
|
||||
log.write('Olympus.HOOKS.LUA', log.ERROR, 'Error loading olympus.dll: '..Olympus.OlympusDLL)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
if isOlympusModuleInitialized~=true then
|
||||
local OlympusName = 'Olympus ' .. version .. ' C++ module';
|
||||
isOlympusModuleInitialized=true;
|
||||
Olympus.DLLsloaded = Olympus.loadDLLs()
|
||||
if Olympus.DLLsloaded then
|
||||
log.write('Olympus.EXPORT.LUA', log.INFO, OlympusName..' successfully loaded.')
|
||||
else
|
||||
log.write('Olympus.EXPORT.LUA', log.ERROR, 'Failed to load '..OlympusName)
|
||||
end
|
||||
else
|
||||
log.write('Olympus.EXPORT.LUA', log.INFO, 'olympus.dll already initialized')
|
||||
end
|
||||
end
|
||||
@ -1,4 +1,4 @@
|
||||
local version = 'v0.1.0-alpha'
|
||||
local version = 'v0.1.1-alpha'
|
||||
|
||||
Olympus = {}
|
||||
Olympus.OlympusDLL = nil
|
||||
|
||||
@ -1,135 +0,0 @@
|
||||
local version = 'v0.1.0-alpha'
|
||||
|
||||
Olympus = {}
|
||||
Olympus.groupIndex = 0
|
||||
Olympus.groupStep = 40
|
||||
|
||||
function Olympus.notify(message, displayFor)
|
||||
trigger.action.outText(message, displayFor)
|
||||
end
|
||||
|
||||
function Olympus.setMissionData(arg, time)
|
||||
local missionData = {}
|
||||
|
||||
-- Bullseye data
|
||||
local bullseyes = {}
|
||||
for i = 0, 2 do
|
||||
local bullseyeVec3 = coalition.getMainRefPoint(i)
|
||||
local bullseyeLatitude, bullseyeLongitude, bullseyeAltitude = coord.LOtoLL(bullseyeVec3)
|
||||
bullseyes[i] = {}
|
||||
bullseyes[i]["latitude"] = bullseyeLatitude
|
||||
bullseyes[i]["longitude"] = bullseyeLongitude
|
||||
end
|
||||
|
||||
-- Units tactical data
|
||||
local unitsData = {}
|
||||
|
||||
local startIndex = Olympus.groupIndex
|
||||
local endIndex = startIndex + Olympus.groupStep
|
||||
local index = 0
|
||||
for groupName, gp in pairs(mist.DBs.groupsByName) do
|
||||
index = index + 1
|
||||
if index > startIndex then
|
||||
if groupName ~= nil then
|
||||
local group = Group.getByName(groupName)
|
||||
if group ~= nil then
|
||||
local controller = group:getController()
|
||||
for index, unit in pairs(group:getUnits()) do
|
||||
local table = {}
|
||||
table["targets"] = {}
|
||||
table["targets"]["visual"] = controller:getDetectedTargets(1)
|
||||
table["targets"]["radar"] = controller:getDetectedTargets(4)
|
||||
table["targets"]["rwr"] = controller:getDetectedTargets(16)
|
||||
table["targets"]["other"] = controller:getDetectedTargets(2, 8, 32)
|
||||
|
||||
table["hasTask"] = controller:hasTask()
|
||||
|
||||
table["ammo"] = unit:getAmmo()
|
||||
table["fuel"] = unit:getFuel()
|
||||
table["life"] = unit:getLife() / unit:getLife0()
|
||||
unitsData[unit:getObjectID()] = table
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if index >= endIndex then
|
||||
break
|
||||
end
|
||||
end
|
||||
if index ~= endIndex then
|
||||
Olympus.groupIndex = 0
|
||||
else
|
||||
Olympus.groupIndex = endIndex
|
||||
end
|
||||
|
||||
-- Airbases data
|
||||
local base = world.getAirbases()
|
||||
local airbases = {}
|
||||
for i = 1, #base do
|
||||
local info = {}
|
||||
local latitude, longitude, altitude = coord.LOtoLL(Airbase.getPoint(base[i]))
|
||||
info["callsign"] = Airbase.getCallsign(base[i])
|
||||
local coalitionID = Airbase.getCoalition(base[i])
|
||||
if coalitionID == 0 then
|
||||
info["coalition"] = "neutral"
|
||||
elseif coalitionID == 1 then
|
||||
info["coalition"] = "red"
|
||||
else
|
||||
info["coalition"] = "blue"
|
||||
end
|
||||
info["latitude"] = latitude
|
||||
info["longitude"] = longitude
|
||||
if Airbase.getUnit(base[i]) then
|
||||
info["unitId"] = Airbase.getUnit(base[i]):getID()
|
||||
end
|
||||
airbases[i] = info
|
||||
end
|
||||
|
||||
local mission = {}
|
||||
mission.theatre = env.mission.theatre
|
||||
|
||||
-- Assemble missionData table
|
||||
missionData["bullseyes"] = bullseyes
|
||||
missionData["unitsData"] = unitsData
|
||||
missionData["airbases"] = airbases
|
||||
missionData["mission"] = mission
|
||||
|
||||
local command = "Olympus.missionData = " .. Olympus.serializeTable(missionData) .. "\n" .. "Olympus.OlympusDLL.setMissionData()"
|
||||
net.dostring_in("export", command)
|
||||
return time + 1
|
||||
end
|
||||
|
||||
function Olympus.serializeTable(val, name, skipnewlines, depth)
|
||||
skipnewlines = skipnewlines or false
|
||||
depth = depth or 0
|
||||
|
||||
local tmp = string.rep(" ", depth)
|
||||
if name then
|
||||
if type(name) == "number" then
|
||||
tmp = tmp .. "[" .. name .. "]" .. " = "
|
||||
else
|
||||
tmp = tmp .. name .. " = "
|
||||
end
|
||||
end
|
||||
|
||||
if type(val) == "table" then
|
||||
tmp = tmp .. "{" .. (not skipnewlines and "\n" or "")
|
||||
for k, v in pairs(val) do
|
||||
tmp = tmp .. Olympus.serializeTable(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and "\n" or "")
|
||||
end
|
||||
tmp = tmp .. string.rep(" ", depth) .. "}"
|
||||
elseif type(val) == "number" then
|
||||
tmp = tmp .. tostring(val)
|
||||
elseif type(val) == "string" then
|
||||
tmp = tmp .. string.format("%q", val)
|
||||
elseif type(val) == "boolean" then
|
||||
tmp = tmp .. (val and "true" or "false")
|
||||
else
|
||||
tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
|
||||
end
|
||||
|
||||
return tmp
|
||||
end
|
||||
|
||||
timer.scheduleFunction(Olympus.setMissionData, {}, timer.getTime() + 1)
|
||||
Olympus.notify("OlympusMission " .. version .. " script loaded correctly", 10)
|
||||
Binary file not shown.
@ -1,42 +0,0 @@
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
START_STRING = "-- Olympus START\n"
|
||||
END_STRING = "-- Olympus END\n"
|
||||
EXPORT_STRING = "local Olympuslfs=require('lfs');dofile(Olympuslfs.writedir()..'Scripts/OlympusExport.lua')\n"
|
||||
|
||||
def main(flag):
|
||||
if flag == "-i":
|
||||
try:
|
||||
with open("Export.lua", "r") as f:
|
||||
shutil.copyfile("Export.lua", "Export.lua.bak")
|
||||
lines = f.readlines()
|
||||
if START_STRING in lines:
|
||||
return
|
||||
except FileNotFoundError:
|
||||
print('File does not exist')
|
||||
|
||||
with open("Export.lua", "a") as f:
|
||||
f.writelines(["\n", START_STRING, EXPORT_STRING, END_STRING, "\n"])
|
||||
elif flag == "-u":
|
||||
try:
|
||||
with open("Export.lua", "r") as f:
|
||||
shutil.copyfile("Export.lua", "Export.lua.bak")
|
||||
lines = f.readlines()
|
||||
except FileNotFoundError:
|
||||
print('File does not exist')
|
||||
|
||||
with open("Export.lua", "w") as f:
|
||||
block = False
|
||||
for line in lines:
|
||||
if line == START_STRING:
|
||||
block = True
|
||||
|
||||
if not block:
|
||||
f.write(line)
|
||||
|
||||
if line == END_STRING:
|
||||
block = False
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1])
|
||||
@ -1,44 +0,0 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['OlympusPatcher.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False,
|
||||
)
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='OlympusPatcher',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
305
scripts/coolEffects.lua
Normal file
305
scripts/coolEffects.lua
Normal file
@ -0,0 +1,305 @@
|
||||
effects = {}
|
||||
effects.shooterName = "TestInfantry"
|
||||
effects.napalmCounter = 1
|
||||
|
||||
effects.fireCounter = 1
|
||||
|
||||
function effects.notify(message, displayFor)
|
||||
trigger.action.outText(message, displayFor, false)
|
||||
end
|
||||
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
----NAPALM
|
||||
|
||||
|
||||
function effects.napalmSingle ()
|
||||
unit = Unit.getByName(effects.shooterName)
|
||||
local unitPos = unit:getPosition().p
|
||||
vec3 = mist.utils.makeVec3GL(unitPos)
|
||||
effects.spawnNapalm (vec3)
|
||||
end
|
||||
|
||||
|
||||
function effects.spawnNapalm (vec3)
|
||||
|
||||
napeName = "napalmStrike" .. effects.napalmCounter
|
||||
effects.napalmCounter = effects.napalmCounter + 1
|
||||
mist.dynAddStatic(
|
||||
{
|
||||
country = 20,
|
||||
category = 'Fortifications',
|
||||
hidden = true,
|
||||
name = napeName,
|
||||
type ="Fuel tank",
|
||||
x = vec3.x,
|
||||
y = vec3.z,
|
||||
heading = 0,
|
||||
} -- end of function
|
||||
)
|
||||
timer.scheduleFunction(effects.explode,vec3, timer.getTime() + 0.1)
|
||||
timer.scheduleFunction(effects.napalam_death,napeName, timer.getTime() + 0.12)
|
||||
end
|
||||
|
||||
function effects.explode(vec3)
|
||||
trigger.action.explosion(vec3, 10)
|
||||
end
|
||||
|
||||
function effects.napalam_death(staticName) --yes i know bad pun, removes the fuel tank after a set time
|
||||
StaticObject.getByName(staticName):destroy()
|
||||
end
|
||||
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
----Basic smoke or fire that despawns
|
||||
function effects.smokeFire ()
|
||||
unit = Unit.getByName(effects.shooterName)
|
||||
local unitPos = unit:getPosition().p
|
||||
vec3 = mist.utils.makeVec3GL(unitPos)
|
||||
effects.createFire (vec3, 2)
|
||||
-- 1 = small smoke and fire
|
||||
-- 2 = medium smoke and fire
|
||||
-- 3 = large smoke and fire
|
||||
-- 4 = huge smoke and fire
|
||||
-- 5 = small smoke
|
||||
-- 6 = medium smoke
|
||||
-- 7 = large smoke
|
||||
-- 8 = huge smoke
|
||||
end
|
||||
|
||||
function effects.createFire (vec3, size)
|
||||
smokeName = "smokeName" .. effects.fireCounter
|
||||
effects.fireCounter = effects.fireCounter + 1
|
||||
trigger.action.effectSmokeBig(vec3 , size , 1, smokeName)
|
||||
trigger.action.explosion(vec3, 1) -- looks wierd to spawn in on flat land without this
|
||||
timer.scheduleFunction(effects.removeFire,smokeName, timer.getTime() + 20) --you could set a timer, or if selected give option to despawn later
|
||||
end
|
||||
|
||||
function effects.removeFire (smokeName)
|
||||
trigger.action.effectSmokeStop(smokeName)
|
||||
end
|
||||
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
----White phosporus secondaries extra effect, like round cooking off
|
||||
--if you up the number going pop to somewhere in the 200-400 region with a white phosporus impact it would look mental cool
|
||||
function effects.secondaries ()
|
||||
unit = Unit.getByName(effects.shooterName)
|
||||
local unitPos = unit:getPosition().p
|
||||
vec3 = mist.utils.makeVec3GL(unitPos)
|
||||
--trigger.action.smoke(vec3 , 2 )
|
||||
for i = 1,math.random(3,10) do
|
||||
angle = mist.utils.toRadian((math.random(1,360)))
|
||||
local randVec = mist.utils.makeVec3GL((mist.getRandPointInCircle(vec3 ,5 , 1 ,0 ,360)))
|
||||
trigger.action.signalFlare(randVec , 2 , angle )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
----Depth Charges
|
||||
-- these also make, on land, good dust clouds for a bomb hit in a sandy area?
|
||||
-- local surface = land.getSurfaceType(mist.utils.makeVec2(unitPos)) -- optional check for water, value 3 or 2
|
||||
|
||||
function effects.depthCharge ()
|
||||
local unit = Unit.getByName(effects.shooterName)
|
||||
local unitPos = unit:getPosition().p
|
||||
|
||||
vec3 = mist.utils.makeVec3GL(unitPos)
|
||||
vec3.y = vec3.y - 1000
|
||||
bang = vec3
|
||||
distance = 20
|
||||
explosionSize = 2
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
trigger.action.explosion(vec3,explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
trigger.action.explosion(vec3,explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0)
|
||||
trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize)
|
||||
timer.scheduleFunction(effects.depthChargeMain,vec3, timer.getTime() + 5)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function effects.depthChargeMain (vec3)
|
||||
explosionSize = 250
|
||||
trigger.action.explosion(vec3,explosionSize)
|
||||
trigger.action.explosion(vec3,explosionSize)
|
||||
vec3.x = vec3.x
|
||||
trigger.action.explosion(vec3,explosionSize)
|
||||
vec3.x = vec3.x - 10
|
||||
trigger.action.explosion(vec3,explosionSize)
|
||||
vec3.z = vec3.z
|
||||
trigger.action.explosion(vec3,explosionSize)
|
||||
vec3.z = vec3.z - 10
|
||||
end
|
||||
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
--------------------------------------------
|
||||
----Normal small explosion
|
||||
|
||||
function effects.normalSmallExplosion (vec3)
|
||||
unit = Unit.getByName(effects.shooterName)
|
||||
local unitPos = unit:getPosition().p
|
||||
vec3 = mist.utils.makeVec3GL(unitPos)
|
||||
trigger.action.explosion(vec3,10)
|
||||
end
|
||||
|
||||
|
||||
|
||||
do
|
||||
longRangeShots = missionCommands.addSubMenu("Effects")
|
||||
missionCommands.addCommand ("Napalm", longRangeShots, effects.napalmSingle)
|
||||
missionCommands.addCommand ("Fire or smoke", longRangeShots, effects.smokeFire)
|
||||
missionCommands.addCommand ("Secondary explosions", longRangeShots, effects.secondaries)
|
||||
missionCommands.addCommand ("Depth Charge", longRangeShots, effects.depthCharge)
|
||||
missionCommands.addCommand ("A regular explosion", longRangeShots, effects.normalSmallExplosion)
|
||||
end
|
||||
|
||||
effects.notify("effects.lua ran", 2)
|
||||
681
scripts/dynamicTanking.lua
Normal file
681
scripts/dynamicTanking.lua
Normal file
@ -0,0 +1,681 @@
|
||||
tankers = {}
|
||||
tankers.tankerName = "TankerClone"
|
||||
|
||||
function tankers.notify(message, displayFor)
|
||||
trigger.action.outText(message, displayFor, false)
|
||||
end
|
||||
|
||||
|
||||
function tankers.setFrequency(freq)
|
||||
|
||||
unit = Unit.getByName(tankers.tankerName)
|
||||
local controller = unit:getController()
|
||||
|
||||
freq = freq or 260 --in MHz, 260 channel 19 is our default tanker thing in refs
|
||||
|
||||
SetFrequency = {
|
||||
id = 'SetFrequency',
|
||||
params = {
|
||||
frequency = freq*1000000 , --in Hz
|
||||
modulation = 0, --AM 0 or FM 1
|
||||
}
|
||||
}
|
||||
|
||||
controller:setCommand(SetFrequency)
|
||||
end
|
||||
|
||||
function tankers.changeCallsign()
|
||||
---https://wiki.hoggitworld.com/view/DCS_command_setCallsign
|
||||
unit = Unit.getByName(tankers.tankerName)
|
||||
local controller = unit:getController()
|
||||
|
||||
SetCallsign = {
|
||||
id = 'SetCallsign',
|
||||
params = {
|
||||
callname = 3, --1 texaco, --2 arco -- 3 shell
|
||||
number = 1, --1 through 9 valid for tankers only ever 1?
|
||||
}
|
||||
}
|
||||
|
||||
controller:setCommand(SetCallsign)
|
||||
end
|
||||
|
||||
--remember to only pick valid tacan channel ranges
|
||||
|
||||
|
||||
-- https://wiki.radioreference.com/index.php/Instrument_Landing_System_(ILS)_Frequencies -- what freqs go with which tacans
|
||||
-- you want the reply channels on the tankers so the fighter tunes the one you want
|
||||
|
||||
function tankers.setTacan(channel, xRay)
|
||||
|
||||
defaultTac = 40
|
||||
defaultXray = true
|
||||
channel = channel or defaultTac -- the channel you want to tell the fighters to enter in, if not provided defaults
|
||||
xRay = xRay or defaultXray -- X or Y are only options so true or false
|
||||
|
||||
unit = Unit.getByName(tankers.tankerName)
|
||||
local controller = unit:getController()
|
||||
|
||||
--tacan maths is easy
|
||||
--for X ray reply it is, channel + 961, Yankee reply is channel + 1087
|
||||
|
||||
if xRay == true then
|
||||
--to not break everyone elses datalink / tacan 37 and above (X)
|
||||
if channel > 36 then
|
||||
freq = channel + 961
|
||||
ActivateBeacon = {
|
||||
id = 'ActivateBeacon',
|
||||
params = {
|
||||
type = 4,
|
||||
system = 3,
|
||||
name = "TKR",
|
||||
callsign = "ABC", --what shows as a listed word / plays as morese code, 3 max no spaces
|
||||
frequency = freq*1000000,
|
||||
}
|
||||
}
|
||||
controller:setCommand(ActivateBeacon)
|
||||
end
|
||||
|
||||
elseif xRay == false then
|
||||
--to not break everyone elses datalink / tacan 30 - 46 (Y) but I don't think the "above" is correct
|
||||
if channel > 29 then
|
||||
freq = channel + 1087
|
||||
ActivateBeacon = {
|
||||
id = 'ActivateBeacon',
|
||||
params = {
|
||||
type = 4,
|
||||
system = 3,
|
||||
name = "TKR",
|
||||
callsign = "ABC", --what shows as a listed word / plays as morese code, 3 max no spaces
|
||||
frequency = freq*1000000,
|
||||
}
|
||||
}
|
||||
controller:setCommand(ActivateBeacon)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tankers.dryPlugTanking () -- for whatever reason this ends up being no fuel transfer?
|
||||
--tankers.setFrequency(260)
|
||||
--tankers.setTacan(41, true)
|
||||
--tankers.changeCallsign()
|
||||
|
||||
unit = Unit.getByName(tankers.tankerName)
|
||||
cvn = Unit.getByName("CVN")
|
||||
local cvnPos = cvn:getPosition().p
|
||||
local tnkrPos = unit:getPosition().p
|
||||
local speed = 250
|
||||
local controller = unit:getController()
|
||||
|
||||
--if you want to try making a tanker do something else
|
||||
--https://www.digitalcombatsimulator.com/en/support/faq/1267/#3307682 maybe? stop conditions etc
|
||||
--personally i think delete the thing if it doesn't work
|
||||
--there is a recovery tanker option, but for me it makes planes stall and hit the floor and we can fake it with this already
|
||||
|
||||
-- this might all seem very over the top compared to the docs, but if you don't do it the tanker instantly RTBs, though you can tank on final which is hillarious
|
||||
|
||||
task1 = {
|
||||
["number"] = 1,
|
||||
["auto"] = false,
|
||||
["id"] = "ControlledTask",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["task"] =
|
||||
{
|
||||
["id"] = "Tanker",
|
||||
["params"] =
|
||||
{
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["task"]
|
||||
["stopCondition"] =
|
||||
{
|
||||
["duration"] = 600,
|
||||
["userFlag"] = "1",
|
||||
}, -- end of ["stopCondition"]
|
||||
}, -- end of ["params"]
|
||||
}
|
||||
|
||||
task2 = {
|
||||
["number"] = 2,
|
||||
["auto"] = false,
|
||||
["id"] = "WrappedAction",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["action"] =
|
||||
{
|
||||
["id"] = "ActivateBeacon",
|
||||
["params"] =
|
||||
{
|
||||
["type"] = 4,
|
||||
["AA"] = false,
|
||||
["callsign"] = "TKR",
|
||||
["modeChannel"] = "Y",
|
||||
["channel"] = 71,
|
||||
["system"] = 5,
|
||||
["unitId"] = 188,
|
||||
["bearing"] = true,
|
||||
["frequency"] = 1032000000,
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["action"]
|
||||
}, -- end of ["params"]
|
||||
}
|
||||
task3 =
|
||||
{
|
||||
["number"] = 3,
|
||||
["auto"] = false,
|
||||
["id"] = "WrappedAction",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["action"] =
|
||||
{
|
||||
["id"] = "SetFrequency",
|
||||
["params"] =
|
||||
{
|
||||
["power"] = 10,
|
||||
["modulation"] = 0,
|
||||
["frequency"] = 305000000,
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["action"]
|
||||
}, -- end of ["params"]
|
||||
}
|
||||
|
||||
task4 =
|
||||
{
|
||||
["number"] = 4,
|
||||
["auto"] = false,
|
||||
["id"] = "WrappedAction",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["action"] =
|
||||
{
|
||||
["id"] = "SetInvisible",
|
||||
["params"] =
|
||||
{
|
||||
["value"] = true,
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["action"]
|
||||
}, -- end of ["params"]
|
||||
}
|
||||
|
||||
point1 = {
|
||||
['speed_locked'] = false,
|
||||
['type'] = 'Turning Point',
|
||||
['action'] = 'Turning Point',
|
||||
['alt_type'] = 'BARO',
|
||||
['y'] = cvnPos.z,
|
||||
['x'] = cvnPos.x,
|
||||
['speed'] = 128.611,
|
||||
['task'] = {
|
||||
['id'] = 'ComboTask',
|
||||
['params'] = {
|
||||
['tasks'] = {
|
||||
[1] = task1, --tanker first
|
||||
[2] = task2, --whatever second
|
||||
[3] = task3,
|
||||
[4] = task4,
|
||||
}
|
||||
}
|
||||
},
|
||||
['alt'] = tnkrPos.y
|
||||
}
|
||||
point2 = {
|
||||
['speed_locked'] = true,
|
||||
['type'] = 'Turning Point',
|
||||
['action'] = 'Turning Point',
|
||||
['alt_type'] = 'BARO',
|
||||
['y'] = 30553,
|
||||
['x'] = 35881,
|
||||
['speed'] = 128.611,
|
||||
['task'] = {
|
||||
['id'] = 'ComboTask',
|
||||
['params'] = {
|
||||
['tasks'] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
['alt'] = 2133.6
|
||||
}
|
||||
|
||||
missionTask =
|
||||
{
|
||||
['id'] = 'Mission',
|
||||
['params'] = {
|
||||
['route'] = {
|
||||
['points'] = {
|
||||
[1] = point1,
|
||||
--[2] = point2,
|
||||
}
|
||||
},
|
||||
['airborne'] = true
|
||||
}
|
||||
}
|
||||
controller:pushTask(missionTask)
|
||||
end
|
||||
|
||||
function tankers.followInFront ()
|
||||
unit = Unit.getByName(tankers.tankerName)
|
||||
local controller = unit:getController()
|
||||
|
||||
FollowAheadOfGroup = {
|
||||
["enabled"] = true,
|
||||
["auto"] = false,
|
||||
["id"] = "Follow",
|
||||
["number"] = 1,
|
||||
["params"] =
|
||||
{
|
||||
["lastWptIndexFlagChangedManually"] = false,
|
||||
["groupId"] = 74,
|
||||
["lastWptIndex"] = 2,
|
||||
["lastWptIndexFlag"] = false,
|
||||
["pos"] =
|
||||
{
|
||||
["y"] = 152.4, --mins for KC 135 to accidentally stern rejoin and overfly
|
||||
["x"] = 1000.8,
|
||||
["z"] = 39.9288,
|
||||
}, -- end of ["pos"]
|
||||
}, -- end of ["params"]
|
||||
}
|
||||
|
||||
controller:pushTask(FollowAheadOfGroup)
|
||||
end
|
||||
|
||||
function tankers.followInFrontClose ()
|
||||
unit = Unit.getByName(tankers.tankerName)
|
||||
local controller = unit:getController()
|
||||
|
||||
FollowAheadOfGroup = {
|
||||
["enabled"] = true,
|
||||
["auto"] = false,
|
||||
["id"] = "Follow",
|
||||
["number"] = 1,
|
||||
["params"] =
|
||||
{
|
||||
["lastWptIndexFlagChangedManually"] = false,
|
||||
["groupId"] = 74,
|
||||
["lastWptIndex"] = 2,
|
||||
["lastWptIndexFlag"] = false,
|
||||
["pos"] =
|
||||
{
|
||||
["y"] = 25, --mins for KC 135 to accidentally stern rejoin and overfly
|
||||
["x"] = 150,
|
||||
["z"] = 41.45,
|
||||
}, -- end of ["pos"]
|
||||
}, -- end of ["params"]
|
||||
}
|
||||
|
||||
controller:pushTask(FollowAheadOfGroup)
|
||||
end
|
||||
|
||||
function tankers.cloneTanker()
|
||||
|
||||
local groupName = 'TankerClone' -- Name of the group in the ME
|
||||
|
||||
group = mist.getGroupData(groupName)
|
||||
group.route = { points = mist.getGroupRoute(groupName, true) }
|
||||
group.groupName = "Tanker1"
|
||||
group.groupId = nil
|
||||
group.units[1].unitId = nil
|
||||
group.units[1].unitName = newName
|
||||
group.country = country
|
||||
group.category = 'AIRPLANE'
|
||||
|
||||
mist.dynAdd(group)
|
||||
|
||||
end
|
||||
|
||||
function tankers.newTanker()
|
||||
|
||||
local groupName = 'TankerClone' -- Name of the group in the ME
|
||||
local cloneGroupPos = Unit.getByName(groupName):getPosition().p
|
||||
cvn = Unit.getByName("CVN")
|
||||
local cvnPos = cvn:getPosition().p
|
||||
|
||||
|
||||
group = mist.getGroupData(groupName)
|
||||
group.route = {
|
||||
["points"] =
|
||||
{
|
||||
[1] =
|
||||
{
|
||||
["alt"] = 2133.6,
|
||||
["action"] = "Turning Point",
|
||||
["alt_type"] = "BARO",
|
||||
["speed"] = 179.86111111111,
|
||||
["task"] =
|
||||
{
|
||||
["id"] = "ComboTask",
|
||||
["params"] =
|
||||
{
|
||||
["tasks"] =
|
||||
{
|
||||
[1] =
|
||||
{
|
||||
["number"] = 1,
|
||||
["auto"] = false,
|
||||
["id"] = "ControlledTask",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["task"] =
|
||||
{
|
||||
["id"] = "Tanker",
|
||||
["params"] =
|
||||
{
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["task"]
|
||||
["stopCondition"] =
|
||||
{
|
||||
["duration"] = 900,
|
||||
}, -- end of ["stopCondition"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["number"] = 2,
|
||||
["auto"] = false,
|
||||
["id"] = "WrappedAction",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["action"] =
|
||||
{
|
||||
["id"] = "ActivateBeacon",
|
||||
["params"] =
|
||||
{
|
||||
["type"] = 4,
|
||||
["AA"] = false,
|
||||
["callsign"] = "TKR",
|
||||
["modeChannel"] = "Y",
|
||||
["channel"] = 71,
|
||||
["system"] = 5,
|
||||
["unitId"] = 188,
|
||||
["bearing"] = true,
|
||||
["frequency"] = 1032000000,
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["action"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of [2]
|
||||
[3] =
|
||||
{
|
||||
["number"] = 3,
|
||||
["auto"] = false,
|
||||
["id"] = "WrappedAction",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["action"] =
|
||||
{
|
||||
["id"] = "SetFrequency",
|
||||
["params"] =
|
||||
{
|
||||
["power"] = 10,
|
||||
["modulation"] = 0,
|
||||
["frequency"] = 260000000,
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["action"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of [3]
|
||||
[4] =
|
||||
{
|
||||
["number"] = 4,
|
||||
["auto"] = false,
|
||||
["id"] = "WrappedAction",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["action"] =
|
||||
{
|
||||
["id"] = "SetInvisible",
|
||||
["params"] =
|
||||
{
|
||||
["value"] = true,
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["action"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of [4]
|
||||
}, -- end of ["tasks"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["task"]
|
||||
["type"] = "Turning Point",
|
||||
["ETA"] = 96.50677034026,
|
||||
["ETA_locked"] = false,
|
||||
["y"] = cvnPos.z,
|
||||
["x"] = cvnPos.x,
|
||||
["formation_template"] = "",
|
||||
["speed_locked"] = true,
|
||||
}, -- end of [1]
|
||||
}, -- end of ["points"]
|
||||
}
|
||||
|
||||
--group.units[1].type = "S-3B Tanker"
|
||||
group.groupName = "Tanker1"
|
||||
group.groupId = nil
|
||||
group.units[1].unitId = nil
|
||||
group.units[1].unitName = newName
|
||||
group.country = country
|
||||
group.category = 'AIRPLANE'
|
||||
group.units[1].x = cloneGroupPos.x
|
||||
group.units[1].y = cloneGroupPos.z
|
||||
group.units[1].z = cloneGroupPos.y
|
||||
group.units[1].speed = 999999
|
||||
|
||||
|
||||
Group.destroy(Group.getByName(groupName))
|
||||
mist.dynAdd(group)
|
||||
--timer.scheduleFunction(mist.dynAdd,group, timer.getTime() + 0.00000000001)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function tankers.startEnrouteTankingTest (vec3) -- this is the one that works well, clone an existing tanker that is currently mission editor tanking
|
||||
|
||||
--tankers.setFrequency(260)
|
||||
--tankers.setTacan(41, true)
|
||||
--tankers.changeCallsign()
|
||||
route = mist.getGroupRoute(tankers.tankerName, true)
|
||||
unit = Unit.getByName(tankers.tankerName)
|
||||
cvn = Unit.getByName("CVN")
|
||||
|
||||
local cvnPos = cvn:getPosition().p
|
||||
|
||||
local vec3 = vec3 or cvnPos
|
||||
route[1].x = unit:getPosition().p.x
|
||||
route[1].y = unit:getPosition().p.z
|
||||
route[2].x = vec3.x
|
||||
route[2].y = vec3.z
|
||||
route[2].z = vec3.y + 100
|
||||
|
||||
mist.goRoute(tankers.tankerName , route )
|
||||
end
|
||||
|
||||
function tankers.hyperSpace (vec3) -- this is the one that works well, clone an existing tanker that is currently mission editor tanking
|
||||
local groupName = 'TankerClone' -- Name of the group in the ME
|
||||
local cloneGroupPos = Unit.getByName(groupName):getPosition().p
|
||||
cvn = Unit.getByName("CVN")
|
||||
local cvnPos = cvn:getPosition().p
|
||||
|
||||
|
||||
group = mist.getGroupData(groupName)
|
||||
group.route = {
|
||||
["points"] =
|
||||
{
|
||||
[1] =
|
||||
{
|
||||
["alt"] = 2133.6,
|
||||
["action"] = "Turning Point",
|
||||
["alt_type"] = "BARO",
|
||||
["speed"] = 179.86111111111,
|
||||
["task"] =
|
||||
{
|
||||
["id"] = "ComboTask",
|
||||
["params"] =
|
||||
{
|
||||
["tasks"] =
|
||||
{
|
||||
[1] =
|
||||
{
|
||||
["number"] = 1,
|
||||
["auto"] = false,
|
||||
["id"] = "ControlledTask",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["task"] =
|
||||
{
|
||||
["id"] = "Tanker",
|
||||
["params"] =
|
||||
{
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["task"]
|
||||
["stopCondition"] =
|
||||
{
|
||||
["duration"] = 900,
|
||||
}, -- end of ["stopCondition"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["number"] = 2,
|
||||
["auto"] = false,
|
||||
["id"] = "WrappedAction",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["action"] =
|
||||
{
|
||||
["id"] = "ActivateBeacon",
|
||||
["params"] =
|
||||
{
|
||||
["type"] = 4,
|
||||
["AA"] = false,
|
||||
["callsign"] = "TKR",
|
||||
["modeChannel"] = "Y",
|
||||
["channel"] = 71,
|
||||
["system"] = 5,
|
||||
["unitId"] = 188,
|
||||
["bearing"] = true,
|
||||
["frequency"] = 1032000000,
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["action"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of [2]
|
||||
[3] =
|
||||
{
|
||||
["number"] = 3,
|
||||
["auto"] = false,
|
||||
["id"] = "WrappedAction",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["action"] =
|
||||
{
|
||||
["id"] = "SetFrequency",
|
||||
["params"] =
|
||||
{
|
||||
["power"] = 10,
|
||||
["modulation"] = 0,
|
||||
["frequency"] = 260000000,
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["action"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of [3]
|
||||
[4] =
|
||||
{
|
||||
["number"] = 4,
|
||||
["auto"] = false,
|
||||
["id"] = "WrappedAction",
|
||||
["enabled"] = true,
|
||||
["params"] =
|
||||
{
|
||||
["action"] =
|
||||
{
|
||||
["id"] = "SetInvisible",
|
||||
["params"] =
|
||||
{
|
||||
["value"] = true,
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["action"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of [4]
|
||||
}, -- end of ["tasks"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["task"]
|
||||
["type"] = "Turning Point",
|
||||
["ETA"] = 96.50677034026,
|
||||
["ETA_locked"] = false,
|
||||
["y"] = cvnPos.z,
|
||||
["x"] = cvnPos.x,
|
||||
["formation_template"] = "",
|
||||
["speed_locked"] = true,
|
||||
}, -- end of [1]
|
||||
}, -- end of ["points"]
|
||||
}
|
||||
|
||||
--group.units[1].type = "S-3B Tanker"
|
||||
group.groupName = "Tanker1"
|
||||
group.groupId = nil
|
||||
group.units[1].unitId = nil
|
||||
group.units[1].unitName = newName
|
||||
group.country = country
|
||||
group.category = 'AIRPLANE'
|
||||
group.units[1].x = cvnPos.x-100
|
||||
group.units[1].y = cvnPos.z
|
||||
group.units[1].z = cloneGroupPos.y
|
||||
group.units[1].heading = 0.000000000001
|
||||
group.units[1].speed = 300
|
||||
|
||||
--Group.destroy(Group.getByName(groupName))
|
||||
mist.dynAdd(group)
|
||||
group.groupName = "Tanker2"
|
||||
group.units[1].x = cvnPos.x+100
|
||||
group.units[1].heading = 3.1415926537
|
||||
group.units[1].y = cvnPos.z
|
||||
mist.dynAdd(group)
|
||||
|
||||
end
|
||||
|
||||
|
||||
handler = {}
|
||||
|
||||
local function protectedCall(...)
|
||||
local status, retval = pcall(...)
|
||||
if not status then
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function tankers.eventHandler (event)
|
||||
if (26 == event.id) then --this is when someone types into a mark
|
||||
local vec3 = mist.utils.makeVec3GL(event.pos)
|
||||
tankers.startEnrouteTankingTest (vec3)
|
||||
end
|
||||
end
|
||||
|
||||
function handler:onEvent(event)
|
||||
protectedCall(tankers.eventHandler, event)
|
||||
end
|
||||
|
||||
do
|
||||
--world.addEventHandler(handler)
|
||||
world.addEventHandler(handler)
|
||||
end
|
||||
|
||||
do
|
||||
longRangeShots = missionCommands.addSubMenu("Dynamic Tanking")
|
||||
missionCommands.addCommand ("Hyperspace entry", longRangeShots, tankers.hyperSpace)
|
||||
missionCommands.addCommand ("Start tanking", longRangeShots, tankers.startEnrouteTankingTest)
|
||||
missionCommands.addCommand ("Frequency change approved", longRangeShots, tankers.setFrequency)
|
||||
missionCommands.addCommand ("Callsign change approved", longRangeShots, tankers.changeCallsign)
|
||||
missionCommands.addCommand ("Tacan change approved", longRangeShots, tankers.setTacan)
|
||||
missionCommands.addCommand ("Start a new tanker", longRangeShots, tankers.newTanker)
|
||||
missionCommands.addCommand ("Rejoin on a unit", longRangeShots, tankers.followInFront)
|
||||
missionCommands.addCommand ("Rejoin close", longRangeShots, tankers.followInFrontClose)
|
||||
|
||||
|
||||
end
|
||||
|
||||
tankers.notify("tankers.lua loaded",2)
|
||||
112
scripts/forceBubble.lua
Normal file
112
scripts/forceBubble.lua
Normal file
@ -0,0 +1,112 @@
|
||||
--Spawn a SAM integrated with IADS
|
||||
--Spawn a normal SAM
|
||||
--SAM bubble shields
|
||||
|
||||
forceBub = {}
|
||||
forceBub.handler = {}
|
||||
forceBub.missileList = {}
|
||||
forceBub.missilesActive = 0
|
||||
forceBub.shieldOn = false
|
||||
|
||||
function forceBub.notify(message, displayFor)
|
||||
trigger.action.outText(message, displayFor, true)
|
||||
end
|
||||
|
||||
function forceBub.setShield()
|
||||
forceBub.notify("Shield on", 2)
|
||||
end
|
||||
|
||||
function forceBub.stopShield()
|
||||
forceBub.shieldOn = false
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function protectedCall(...)
|
||||
local status, retval = pcall(...)
|
||||
if not status then
|
||||
--rf.notify("Caught error " .. retval,2)
|
||||
end
|
||||
end
|
||||
|
||||
function forceBub.handler:onEvent(event)
|
||||
protectedCall(forceBub.eventHandler, event)
|
||||
end
|
||||
|
||||
function forceBub.checkMissiles ()
|
||||
local currentTime = timer.getTime()
|
||||
if forceBub.missilesActive > 0 then
|
||||
for index, data in pairs(forceBub.missileList) do
|
||||
output = mist.utils.tableShow(forceBub.missileList[index])
|
||||
if forceBub.missileList[index].exists == true then
|
||||
if Object.isExist(forceBub.missileList[index].weapon) == true then
|
||||
forceBub.missileList[index].pos = forceBub.missileList[index].weapon:getPosition()
|
||||
|
||||
|
||||
local missilePosition = forceBub.missileList[index].pos.p
|
||||
|
||||
unit = Unit.getByName("Test")
|
||||
local unitPosition = unit:getPosition().p
|
||||
|
||||
local distance = mist.utils.get3DDist(unitPosition , missilePosition )
|
||||
forceBub.notify(distance,1)
|
||||
|
||||
if forceBub.shieldOn == true and distance < 100 then --this distance is the sweet spot any less and you probably take damage and die, less than 75 death
|
||||
|
||||
trigger.action.explosion(missilePosition , 1) --just blows up the missile
|
||||
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
forceBub.missileList[index] = nil
|
||||
forceBub.missilesActive = forceBub.missilesActive - 1
|
||||
end
|
||||
else
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
timer.scheduleFunction(forceBub.checkMisProtectCall,{},currentTime + 0.01)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function forceBub.eventHandler (event)
|
||||
--forceBub.notify(mist.utils.tableShow(event),10)
|
||||
if (event.id == 1) then
|
||||
--check if weapon is a missile
|
||||
--rf.notify("Missile fired id " .. event.weapon.id_ ,2)
|
||||
forceBub.notify(mist.utils.tableShow(Weapon.getDesc(event.weapon)),10)
|
||||
if Weapon.getDesc(event.weapon).missileCategory == 2 then
|
||||
local newMis = {}
|
||||
newMis.id = event.weapon.id_
|
||||
newMis.pos = event.weapon:getPosition()
|
||||
newMis.weapon = event.weapon
|
||||
newMis.exists = Object.isExist(newMis.weapon)
|
||||
forceBub.missileList[event.weapon.id_] = newMis
|
||||
forceBub.missilesActive = forceBub.missilesActive + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function forceBub.checkMisProtectCall()
|
||||
protectedCall(forceBub.checkMissiles,{})
|
||||
end
|
||||
|
||||
function forceBub.setShield()
|
||||
forceBub.shieldOn = true
|
||||
end
|
||||
|
||||
do
|
||||
forceField = missionCommands.addSubMenu("Force Field")
|
||||
missionCommands.addCommand ("Forcefield on", forceField, forceBub.setShield)
|
||||
missionCommands.addCommand ("Stop Field", forceField, forceBub.stopShield)
|
||||
end
|
||||
|
||||
do
|
||||
world.addEventHandler(forceBub.handler)
|
||||
end
|
||||
|
||||
protectedCall(forceBub.checkMissiles,{})
|
||||
forceBub.notify("forceBubble.lua loaded", 2)
|
||||
628
scripts/poleGen.lua
Normal file
628
scripts/poleGen.lua
Normal file
@ -0,0 +1,628 @@
|
||||
--max range, altitude and it fails?
|
||||
--shoot right up
|
||||
--fix sa10 and sa 11
|
||||
|
||||
--different static layouts on a carrier depending on what is going on
|
||||
--guns on a static ship at sea?
|
||||
|
||||
|
||||
pg = {}
|
||||
handler = {}
|
||||
pg.name = "Sam"
|
||||
pg.cloneName = "Clone"
|
||||
pg.fakeTargetName = "Player"
|
||||
pg.samCounter = 1
|
||||
pg.droneAlt = 20000
|
||||
pg.delay = 40
|
||||
pg.missileSpeed = 565
|
||||
pg.samLoc = {}
|
||||
pg.samLoc.x = 1
|
||||
pg.samLoc.y = 1
|
||||
pg.samLoc.z = 1
|
||||
pg.missilesActive = 0
|
||||
pg.droneName = nil
|
||||
pg.droneSpeed = 300
|
||||
pg.hidden = false
|
||||
pg.samDB = {[1] = {["missileDelay"] = 40, ["missileSpeed"] = 770},
|
||||
[2] = {["missileDelay"] = 40, ["missileSpeed"] = 770},
|
||||
[3] = {["missileDelay"] = 120, ["missileSpeed"] = 550},
|
||||
[4] = {["missileDelay"] = 40, ["missileSpeed"] = 770},
|
||||
[5] = {["missileDelay"] = 65, ["missileSpeed"] = 770},
|
||||
[6] = {["missileDelay"] = 60, ["missileSpeed"] = 500},
|
||||
[7] = {["missileDelay"] = 40, ["missileSpeed"] = 770},
|
||||
[8] = {["missileDelay"] = 40, ["missileSpeed"] = 770},
|
||||
[9] = {["missileDelay"] = 40, ["missileSpeed"] = 770},
|
||||
[10] = {["missileDelay"] = 60, ["missileSpeed"] = 1400},
|
||||
}
|
||||
|
||||
function pg.notify(message, displayFor)
|
||||
trigger.action.outText(message, displayFor, false)
|
||||
end
|
||||
|
||||
|
||||
function pg.fakeSam(vec3)
|
||||
|
||||
playerTarget = Unit.getByName(pg.fakeTargetName)
|
||||
pointFakeTarget = playerTarget:getPosition().p
|
||||
vec3 = vec3 or pg.samLoc
|
||||
|
||||
vecSub = mist.vec.sub(pointFakeTarget , vec3)
|
||||
planeHeading = mist.utils.getDir(vecSub)
|
||||
missileType = 2
|
||||
pg.spawnDrone (vec3,planeHeading,playerTarget,missileType)
|
||||
|
||||
--pg.notify("FakeSam Ran", 10)
|
||||
|
||||
targetID = Group.getByName("TargetDrone" .. pg.samCounter):getUnit(1):getID()
|
||||
samGroup = Group.getByName("poleGenerator" .. pg.samCounter)
|
||||
vars = {[1] = targetID, [2] = samGroup}
|
||||
timer.scheduleFunction(pg.attack ,vars, timer.getTime() + 1)
|
||||
pg.samCounter = pg.samCounter + 1
|
||||
|
||||
end
|
||||
|
||||
|
||||
function pg.spawnSamSA2 (vec3,heading)
|
||||
--where
|
||||
--name
|
||||
group = {}
|
||||
group.groupName = "poleGenerator" .. pg.samCounter
|
||||
group.units = {
|
||||
[1] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["hidden"] = pg.hidden,
|
||||
["type"] = "S_75M_Volhov",
|
||||
--["unitId"] = 35,
|
||||
["y"] = vec3.z-40,
|
||||
["x"] = vec3.x-40,
|
||||
--["name"] = "Ground-1-2",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "SNR_75V",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z,
|
||||
["x"] = vec3.x,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [2]
|
||||
}
|
||||
group.hidden = pg.hidden
|
||||
group.category = "VEHICLE"
|
||||
group.country = 54
|
||||
mist.dynAdd(group)
|
||||
--heading
|
||||
end
|
||||
|
||||
function pg.spawnSamSA3 (vec3,heading)
|
||||
--where
|
||||
--name
|
||||
group = {}
|
||||
group.groupName = "poleGenerator" .. pg.samCounter
|
||||
group.units = {
|
||||
[1] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["hidden"] = pg.hidden,
|
||||
["type"] = "snr s-125 tr",
|
||||
--["unitId"] = 35,
|
||||
["y"] = vec3.z-40,
|
||||
["x"] = vec3.x-40,
|
||||
--["name"] = "Ground-1-2",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "5p73 s-125 ln",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z,
|
||||
["x"] = vec3.x,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [2]
|
||||
}
|
||||
group.hidden = pg.hidden
|
||||
group.category = "VEHICLE"
|
||||
group.country = 54
|
||||
mist.dynAdd(group)
|
||||
--heading
|
||||
end
|
||||
|
||||
function pg.spawnSamSA5 (vec3,heading)
|
||||
--where
|
||||
--name
|
||||
group = {}
|
||||
group.groupName = "poleGenerator" .. pg.samCounter
|
||||
group.units = {
|
||||
[1] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["hidden"] = pg.hidden,
|
||||
["type"] = "RPC_5N62V",
|
||||
--["unitId"] = 35,
|
||||
["y"] = vec3.z-40,
|
||||
["x"] = vec3.x-40,
|
||||
--["name"] = "Ground-1-2",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "RLS_19J6",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z,
|
||||
["x"] = vec3.x,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [2]
|
||||
[3] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "S-200_Launcher",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z-80,
|
||||
["x"] = vec3.x-80,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [3]
|
||||
}
|
||||
group.hidden = pg.hidden
|
||||
group.category = "VEHICLE"
|
||||
group.country = 54
|
||||
mist.dynAdd(group)
|
||||
--heading
|
||||
end
|
||||
|
||||
function pg.spawnSamSA6 (vec3,heading)
|
||||
--where
|
||||
--name
|
||||
group = {}
|
||||
group.groupName = "poleGenerator" .. pg.samCounter
|
||||
group.units = {
|
||||
[1] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["hidden"] = pg.hidden,
|
||||
["type"] = "Kub 1S91 str",
|
||||
--["unitId"] = 35,
|
||||
["y"] = vec3.z-40,
|
||||
["x"] = vec3.x-40,
|
||||
--["name"] = "Ground-1-2",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "Kub 2P25 ln",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z,
|
||||
["x"] = vec3.x,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [2]
|
||||
}
|
||||
group.hidden = pg.hidden
|
||||
group.category = "VEHICLE"
|
||||
group.country = 54
|
||||
mist.dynAdd(group)
|
||||
--heading
|
||||
end
|
||||
|
||||
function pg.spawnSamSA10 (vec3,heading)
|
||||
--where
|
||||
--name
|
||||
group = {}
|
||||
group.groupName = "poleGenerator" .. pg.samCounter
|
||||
group.units = {
|
||||
[1] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["hidden"] = pg.hidden,
|
||||
["type"] = "S-300PS 40B6M tr",
|
||||
--["unitId"] = 35,
|
||||
["y"] = vec3.z,
|
||||
["x"] = vec3.x,
|
||||
--["name"] = "Ground-1-2",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "S-300PS 64H6E sr",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z-10,
|
||||
["x"] = vec3.x-10,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [2]
|
||||
[3] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "S-300PS 54K6 cp",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z-20,
|
||||
["x"] = vec3.x-20,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [3]
|
||||
[4] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "S-300PS 5P85C ln",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z-40,
|
||||
["x"] = vec3.x-40,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [4]
|
||||
}
|
||||
group.hidden = pg.hidden
|
||||
group.category = "VEHICLE"
|
||||
group.country = 54
|
||||
mist.dynAdd(group)
|
||||
--heading
|
||||
end
|
||||
|
||||
function pg.spawnSamSA11 (vec3,heading)
|
||||
--where
|
||||
--name
|
||||
group = {}
|
||||
group.groupName = "poleGenerator" .. pg.samCounter
|
||||
group.units = {
|
||||
[1] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["hidden"] = pg.hidden,
|
||||
["type"] = "SA-11 Buk SR 9S18M1",
|
||||
--["unitId"] = 35,
|
||||
["y"] = vec3.z-40,
|
||||
["x"] = vec3.x-40,
|
||||
--["name"] = "Ground-1-2",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "SA-11 Buk CC 9S470M1",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z,
|
||||
["x"] = vec3.x,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [2]
|
||||
[2] =
|
||||
{
|
||||
["skill"] = "High",
|
||||
["coldAtStart"] = false,
|
||||
["type"] = "SA-11 Buk LN 9A310M1",
|
||||
--["unitId"] = 34,
|
||||
["y"] = vec3.z,
|
||||
["x"] = vec3.x,
|
||||
--["name"] = "Ground-1-1",
|
||||
["heading"] = heading+math.pi,
|
||||
["playerCanDrive"] = false,
|
||||
}, -- end of [2]
|
||||
}
|
||||
group.hidden = pg.hidden
|
||||
group.category = "VEHICLE"
|
||||
group.country = 54
|
||||
mist.dynAdd(group)
|
||||
--heading
|
||||
end
|
||||
|
||||
|
||||
|
||||
function pg.spawnDrone(vec3,planeHeading,playerTarget,missileType)
|
||||
-- where is the plane going to be in x seconds
|
||||
playerTargetPos = playerTarget:getPosition().p
|
||||
futurePlayerTargetPos = playerTargetPos
|
||||
playerMotionVec = Object.getVelocity(playerTarget)
|
||||
|
||||
--work out what type of SAM we are shooting to work out the delay, missile speed etc
|
||||
|
||||
if missileType == 2 then
|
||||
pg.delay = pg.samDB[2].missileDelay
|
||||
pg.missileSpeed = pg.samDB[2].missileSpeed
|
||||
elseif missileType == 3 then
|
||||
pg.delay = pg.samDB[3].missileDelay
|
||||
pg.missileSpeed = pg.samDB[3].missileSpeed
|
||||
elseif missileType == 5 then
|
||||
pg.delay = pg.samDB[5].missileDelay
|
||||
pg.missileSpeed = pg.samDB[5].missileSpeed
|
||||
elseif missileType == 6 then
|
||||
pg.delay = pg.samDB[6].missileDelay
|
||||
pg.missileSpeed = pg.samDB[5].missileSpeed
|
||||
elseif missileType == 10 then
|
||||
pg.delay = pg.samDB[10].missileDelay
|
||||
pg.missileSpeed = pg.samDB[10].missileSpeed
|
||||
elseif missileType == 11 then
|
||||
pg.delay = pg.samDB[11].missileDelay
|
||||
pg.missileSpeed = pg.samDB[11].missileSpeed
|
||||
else --assume SA2
|
||||
pg.delay = pg.samDB[2].missileDelay
|
||||
pg.missileSpeed = pg.samDB[2].missileSpeed
|
||||
end
|
||||
|
||||
futurePlayerTargetPos.x = playerTargetPos.x + playerMotionVec.x*pg.delay
|
||||
futurePlayerTargetPos.y = playerTargetPos.y + playerMotionVec.y*pg.delay
|
||||
futurePlayerTargetPos.z = playerTargetPos.z + playerMotionVec.z*pg.delay
|
||||
droneTurnPoint = mist.projectPoint(futurePlayerTargetPos, 10000 ,planeHeading+math.pi)
|
||||
--this is where the plane will be when the missile is launched
|
||||
|
||||
|
||||
|
||||
--pythago to get hyp
|
||||
--x^2 + y^x = hyp^2
|
||||
x = mist.utils.get2DDist(futurePlayerTargetPos,vec3)
|
||||
|
||||
y = playerTargetPos.y
|
||||
--pg.notify(y,5)
|
||||
hyp = math.sqrt(x^2 + y^2)
|
||||
roughFlightTime = hyp /pg.missileSpeed-- distance / speed
|
||||
|
||||
futurePlayerTargetPos.x = futurePlayerTargetPos.x + playerMotionVec.x*roughFlightTime
|
||||
futurePlayerTargetPos.y = futurePlayerTargetPos.y + playerMotionVec.y*roughFlightTime
|
||||
futurePlayerTargetPos.z = futurePlayerTargetPos.z + playerMotionVec.z*roughFlightTime
|
||||
--this is where the plane will be when the missile arrives at its altitude
|
||||
|
||||
--now we need to work out where the drone is going to go
|
||||
vecSub = mist.vec.sub(vec3,futurePlayerTargetPos)
|
||||
heading = mist.utils.getDir(vecSub) --heading between picked location and future pos
|
||||
extendDistance = x + 10000
|
||||
|
||||
alt = (((futurePlayerTargetPos.y) * extendDistance)/x)
|
||||
|
||||
droneAtTimePos = mist.projectPoint(vec3, extendDistance ,heading +math.pi)
|
||||
|
||||
extendDistance = extendDistance + pg.droneSpeed*roughFlightTime
|
||||
droneAtStartPos = mist.projectPoint(vec3, extendDistance ,heading +math.pi)
|
||||
--we want to curve the missile in the players direction
|
||||
--planeHeading
|
||||
|
||||
pg.makeDrone(droneAtStartPos,heading, droneAtTimePos, futurePlayerTargetPos,alt,droneTurnPoint)
|
||||
if missileType == 2 then
|
||||
pg.spawnSamSA2 (vec3,heading)
|
||||
elseif missileType == 3 then
|
||||
pg.spawnSamSA3 (vec3,heading)
|
||||
elseif missileType == 5 then
|
||||
pg.spawnSamSA5 (vec3,heading)
|
||||
elseif missileType == 6 then
|
||||
pg.spawnSamSA6 (vec3,heading)
|
||||
elseif missileType == 10 then
|
||||
pg.spawnSamSA10 (vec3,heading)
|
||||
else --assume SA2
|
||||
pg.spawnSamSA2 (vec3,heading)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
function pg.makeDrone(spawnVec,heading, routeVec, nextRouteVec,alt,droneTurnPoint)
|
||||
--this spawns in the drone
|
||||
group = DroneClone
|
||||
group.groupName = "TargetDrone" .. pg.samCounter
|
||||
group.groupId = nil
|
||||
group.units[1].unitId = nil
|
||||
group.units[1].unitName = nil
|
||||
group.units[1].y = spawnVec.z
|
||||
group.units[1].x = spawnVec.x
|
||||
group.units[1].heading = heading
|
||||
group.units[1].alt = alt
|
||||
group.route["points"][2] = group.route["points"][1]
|
||||
group.route["points"][3] = group.route["points"][1]
|
||||
group.route["points"][1]["y"] = routeVec.z
|
||||
group.route["points"][1]["x"] = routeVec.x
|
||||
group.route["points"][1]["alt"] = alt
|
||||
group.route["points"][2]["y"] = nextRouteVec.z
|
||||
group.route["points"][2]["x"] = nextRouteVec.x
|
||||
group.route["points"][2]["alt"] = alt
|
||||
group.route["points"][3]["y"] = droneTurnPoint.z
|
||||
group.route["points"][3]["x"] = droneTurnPoint.x
|
||||
group.route["points"][3]["alt"] = alt
|
||||
group.countryId = 56
|
||||
group.category = 'AIRPLANE'
|
||||
mist.dynAdd(group)
|
||||
end
|
||||
|
||||
|
||||
function pg.attack (vars)
|
||||
targetID = vars[1]
|
||||
samGroup = vars[2]
|
||||
AttackUnit = {
|
||||
id = 'AttackUnit',
|
||||
params = {
|
||||
unitId = targetID,
|
||||
attackQtyLimit = true,
|
||||
attackQty = 1,
|
||||
}
|
||||
}
|
||||
|
||||
local controller = samGroup:getController()
|
||||
controller:pushTask(AttackUnit)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function pg.radarOff ()
|
||||
group = Group.getByName(pg.name)
|
||||
local controller = group:getController()
|
||||
controller:setOption(9,1)
|
||||
end
|
||||
|
||||
function pg.radarOn ()
|
||||
group = Group.getByName(pg.name)
|
||||
local controller = group:getController()
|
||||
controller:setOption(9,0)
|
||||
end
|
||||
|
||||
DroneClone=
|
||||
{
|
||||
["modulation"] = 0,
|
||||
["tasks"] =
|
||||
{
|
||||
}, -- end of ["tasks"]
|
||||
["task"] = "Reconnaissance",
|
||||
["uncontrolled"] = false,
|
||||
["route"] =
|
||||
{
|
||||
["points"] =
|
||||
{
|
||||
[1] =
|
||||
{
|
||||
["alt"] = 2000,
|
||||
["action"] = "Turning Point",
|
||||
["alt_type"] = "BARO",
|
||||
["speed"] = 82.222222222222,
|
||||
["task"] =
|
||||
{
|
||||
["id"] = "ComboTask",
|
||||
["params"] =
|
||||
{
|
||||
["tasks"] =
|
||||
{}, -- end of ["tasks"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["task"]
|
||||
["type"] = "Turning Point",
|
||||
["ETA"] = 0,
|
||||
["ETA_locked"] = true,
|
||||
["y"] = 0,
|
||||
["x"] = 0,
|
||||
["formation_template"] = "",
|
||||
["speed_locked"] = true,
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["alt"] = 2000,
|
||||
["action"] = "Turning Point",
|
||||
["alt_type"] = "BARO",
|
||||
["speed"] = 82.222222222222,
|
||||
["task"] =
|
||||
{
|
||||
["id"] = "ComboTask",
|
||||
["params"] =
|
||||
{
|
||||
["tasks"] =
|
||||
{
|
||||
}, -- end of ["tasks"]
|
||||
}, -- end of ["params"]
|
||||
}, -- end of ["task"]
|
||||
["type"] = "Turning Point",
|
||||
["ETA"] = 157.20107538291,
|
||||
["ETA_locked"] = false,
|
||||
["y"] = 0,
|
||||
["x"] = 0,
|
||||
["formation_template"] = "",
|
||||
["speed_locked"] = true,
|
||||
}, -- end of [2]
|
||||
}, -- end of ["points"]
|
||||
}, -- end of ["route"]
|
||||
--["groupId"] = 1,
|
||||
["hidden"] = pg.hidden,
|
||||
["units"] =
|
||||
{
|
||||
[1] =
|
||||
{
|
||||
["alt"] = 2000,
|
||||
["alt_type"] = "BARO",
|
||||
["livery_id"] = "'camo' scheme",
|
||||
["skill"] = "High",
|
||||
["speed"] = 82.222222222222,
|
||||
["type"] = "MQ-9 Reaper",
|
||||
--["unitId"] = 1,
|
||||
--["psi"] = -3.129323330636,
|
||||
["y"] = 0,
|
||||
["x"] = 0,
|
||||
["payload"] =
|
||||
{
|
||||
["pylons"] =
|
||||
{
|
||||
}, -- end of ["pylons"]
|
||||
["fuel"] = 1300,
|
||||
["flare"] = 0,
|
||||
["chaff"] = 0,
|
||||
["gun"] = 100,
|
||||
}, -- end of ["payload"]
|
||||
["heading"] = 0.5,
|
||||
["callsign"] =
|
||||
{
|
||||
[1] = 1,
|
||||
[2] = 1,
|
||||
[3] = 1,
|
||||
["name"] = "Enfield11",
|
||||
}, -- end of ["callsign"]
|
||||
["onboard_num"] = "010",
|
||||
}, -- end of [1]
|
||||
}, -- end of ["units"]
|
||||
["y"] = 0,
|
||||
["x"] = 0,
|
||||
["communication"] = true,
|
||||
["start_time"] = 0,
|
||||
["frequency"] = 124,
|
||||
}
|
||||
|
||||
|
||||
local function protectedCall(...)
|
||||
local status, retval = pcall(...)
|
||||
if not status then
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function handler:onEvent(event)
|
||||
protectedCall(pg.eventHandler, event)
|
||||
end
|
||||
|
||||
function pg.eventHandler (event)
|
||||
if (26 == event.id) then --this is when someone types into a mark
|
||||
local vec3 = mist.utils.makeVec3GL(event.pos)
|
||||
pg.fakeSam (vec3)
|
||||
end
|
||||
end
|
||||
|
||||
function handler:onEvent(event)
|
||||
protectedCall(pg.eventHandler, event)
|
||||
end
|
||||
|
||||
|
||||
do
|
||||
longRangeShots = missionCommands.addSubMenu("SAM")
|
||||
missionCommands.addCommand ("Generate pole", longRangeShots, pg.fakeSam)
|
||||
world.addEventHandler(handler)
|
||||
end
|
||||
|
||||
pg.notify("poleGen.lua",10)
|
||||
|
||||
319
scripts/raisedShots.lua
Normal file
319
scripts/raisedShots.lua
Normal file
@ -0,0 +1,319 @@
|
||||
shots = {} --https://www.youtube.com/watch?v=XNtTEibFvlQ mandatory terrible listening
|
||||
shots.shooterName = "TestInfantry"
|
||||
shots.targetName = "TestTarget1"
|
||||
|
||||
function shots.notify(message, displayFor)
|
||||
trigger.action.outText(message, displayFor, false)
|
||||
end
|
||||
|
||||
|
||||
|
||||
--infantry
|
||||
|
||||
function shots.set556 () --red
|
||||
roundVelocity = 910
|
||||
unitBarrelHeight = 1
|
||||
shotsToFire = 5
|
||||
shotDelay = 4.5
|
||||
shots.notify("5.56 M4 Georgia", 2)
|
||||
shots.fire()
|
||||
end
|
||||
|
||||
function shots.set556SAW () --red
|
||||
roundVelocity = 915
|
||||
unitBarrelHeight = 0.4
|
||||
shotsToFire = 5
|
||||
shotDelay = 4.5
|
||||
shots.notify("5.56 M249 SAW", 2)
|
||||
shots.fire()
|
||||
|
||||
end
|
||||
|
||||
function shots.setAk74() --red
|
||||
roundVelocity = 900
|
||||
unitBarrelHeight = 0.9
|
||||
shotsToFire = 5
|
||||
shotDelay = 4.5
|
||||
shots.notify("Ak74", 2)
|
||||
shots.fire()
|
||||
end
|
||||
|
||||
--technicals
|
||||
|
||||
function shots.hmmwv() --red
|
||||
roundVelocity = 928
|
||||
unitBarrelHeight = 2.6
|
||||
shotsToFire = 5
|
||||
shotDelay = 2.5
|
||||
shots.notify("Humm drumm Vee", 2)
|
||||
shots.fire()
|
||||
shots.notify(unitBarrelHeight,2)
|
||||
|
||||
end
|
||||
|
||||
function shots.technicalDHSKA() --green
|
||||
roundVelocity = 928
|
||||
unitBarrelHeight = 2.2
|
||||
shotsToFire = 5
|
||||
shotDelay = 2.5
|
||||
shots.notify("technicalDHSKA", 2)
|
||||
shots.fire()
|
||||
shots.notify(unitBarrelHeight,2)
|
||||
|
||||
end
|
||||
|
||||
function shots.cobra() --green
|
||||
roundVelocity = 928
|
||||
unitBarrelHeight = 2.85
|
||||
shotsToFire = 5
|
||||
shotDelay = 2.6
|
||||
shots.notify("Cobra", 2)
|
||||
shots.fire()
|
||||
shots.notify(unitBarrelHeight,2)
|
||||
|
||||
end
|
||||
--IFVs
|
||||
|
||||
function shots.setWarrior() --white
|
||||
roundVelocity = 1070
|
||||
unitBarrelHeight = 2.28
|
||||
shotsToFire = 3
|
||||
shotDelay = 6.3
|
||||
shots.fire()
|
||||
end
|
||||
|
||||
function shots.setBMP2() --red
|
||||
roundVelocity = 970
|
||||
unitBarrelHeight = 1.95
|
||||
shotsToFire = 3
|
||||
shotDelay = 6
|
||||
shots.fire()
|
||||
end
|
||||
|
||||
--Tanks
|
||||
|
||||
function shots.m1a1() --red
|
||||
roundVelocity = 928
|
||||
unitBarrelHeight = 2.15
|
||||
shotsToFire = 5
|
||||
shotDelay = 3
|
||||
shots.notify("Abrams 50 cal", 2)
|
||||
shots.fire()
|
||||
shots.notify(unitBarrelHeight,2)
|
||||
|
||||
end
|
||||
|
||||
function shots.t55() --red and green
|
||||
roundVelocity = 928
|
||||
unitBarrelHeight = 1.75
|
||||
shotsToFire = 5
|
||||
shotDelay = 2.6
|
||||
shots.notify("T-72B", 2)
|
||||
shots.fire()
|
||||
shots.notify(unitBarrelHeight,2)
|
||||
end
|
||||
|
||||
---aaaaaaaaaaaaaaaa
|
||||
|
||||
function shots.ZSU57() --red
|
||||
roundVelocity = 1070
|
||||
shotsToFire = 2
|
||||
shotDelay = 10.5
|
||||
shots.notify("ZSU57", 2)
|
||||
unitMaxRange = 6000
|
||||
shots.fireAAA()
|
||||
end
|
||||
|
||||
function shots.ZSU23() --red
|
||||
roundVelocity = 1050
|
||||
shotsToFire = 2
|
||||
shotDelay = 12
|
||||
shots.notify("ZSU23", 2)
|
||||
unitMaxRange = 2000
|
||||
shots.fireAAA()
|
||||
end
|
||||
|
||||
function shots.vulcan() --red
|
||||
roundVelocity = 1030
|
||||
shotsToFire = 5
|
||||
shotDelay = 5
|
||||
shots.notify("Vulcan M163", 2)
|
||||
unitMaxRange = 1500
|
||||
shots.fireAAA()
|
||||
end
|
||||
|
||||
function shots.flak18() --red and green
|
||||
roundVelocity = 870
|
||||
shotsToFire = 1
|
||||
shotDelay = 10.5
|
||||
shots.notify("Flak 18", 2)
|
||||
unitMaxRange = 4000
|
||||
shots.fireAAA()
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
-- This one is really obvious, however I set towards the end of this file the "parameters" of the shots.
|
||||
function shots.fire()
|
||||
unit = Unit.getByName(shots.shooterName)
|
||||
target = Unit.getByName(shots.targetName)
|
||||
local targetMotionVec = Object.getVelocity(target) --if you don't want to do this i.e. shoot a point send a nil or a vec3 of 0's
|
||||
--local targetMotionVec = nil
|
||||
local targetPos = target:getPosition().p
|
||||
shots.calculateAngle(roundVelocity, unit, targetPos, unitBarrelHeight, shotsToFire,shotDelay, targetMotionVec)
|
||||
end
|
||||
|
||||
--main bit that does the maths for simulating a "roughly level" fire fight, not to be used when aiming AAA at aircraft
|
||||
function shots.calculateAngle(v, unit, targetPos, unitBarrelHeight, shotsToFire,shotDelay, targetMotionVector)
|
||||
--v muzzle velocity
|
||||
--unit is unit object you want shooting
|
||||
--targetPos is a position on the ground, doesn't have to be a targets actual location
|
||||
--unitBarrelHeigh is the height the gun is at when it fires
|
||||
--shotsToFire is how many rounds to shoot, 5 is a nice number except for large calibre slow guns
|
||||
--shotDelay how long it on average takes to aim from scratch at something and shoot, mostly used in aiming lead
|
||||
--targetMotionVector a vec3 of the targets motion if nil just shoots at a spot
|
||||
|
||||
g = 9.81 -- gravity, change if on the moon veltro you comment reading prick
|
||||
|
||||
local unitPos = unit:getPosition().p
|
||||
local x = mist.utils.get2DDist(unitPos,targetPos) -- horizontal range
|
||||
local x3d = mist.utils.get3DDist(unitPos,targetPos) -- slant range
|
||||
|
||||
y = targetPos.y - unitPos.y
|
||||
y = y - unitBarrelHeight
|
||||
|
||||
--works out some stuff for trig later, like x,y and hypoteneueussueee
|
||||
|
||||
if targetMotionVector == nil then
|
||||
--no moving? nothing to ammend
|
||||
else --work out where target will be when the bullet arrives
|
||||
shotDelay = shotDelay + x3d/v --time taken to aim and time for bullet to fly to spot
|
||||
newPosition = mist.utils.tableShow(targetMotionVector)
|
||||
targetPos.x = targetPos.x + targetMotionVector.x*shotDelay
|
||||
targetPos.y = targetPos.y + targetMotionVector.y*shotDelay
|
||||
targetPos.z = targetPos.z + targetMotionVector.z*shotDelay
|
||||
end
|
||||
|
||||
x = x - 10 --we actually are aiming 10m in front always so need to remove this
|
||||
|
||||
local inner = v^4 - g * (g * x^2 + 2 * y * v^2) -- this is the inner bit of the quadratic equation for ease of code
|
||||
|
||||
if inner < 0 then
|
||||
-- No solution exists for these parameters, too far away do nothing we can't hit it, saves us crashing if sqrt of negative
|
||||
else
|
||||
local angle2 = math.atan((v^2 - math.sqrt(inner)) / (g * x)) -- do the whole quadratic equation
|
||||
-- we didn't need to do the +- sqrt b^2..... bits as we care about the flat path not the one shot miles up falling down
|
||||
|
||||
local aimUp = 10 * math.tan(angle2)*math.cos(angle2) -- we have to tell dcs to "aim up" at a point 10m ahead of it, this is distance * tan(angle) , so where the fuck has the cos come from? That is because aim correction for shooting up and down is basically modfied by cos(angle) so lazy correction and dcs can't shoot vertically up
|
||||
local xPosDifference = (targetPos.x - unitPos.x)
|
||||
local zPosDifference = (targetPos.z - unitPos.z)
|
||||
local hyp = math.sqrt((xPosDifference*xPosDifference) + (zPosDifference*zPosDifference))
|
||||
xPosDifference = (xPosDifference /hyp) * 10
|
||||
zPosDifference = (zPosDifference / hyp) * 10
|
||||
|
||||
unitPos.x = unitPos.x + xPosDifference
|
||||
unitPos.z = unitPos.z + zPosDifference
|
||||
|
||||
--that was all basic trig maths
|
||||
|
||||
local controller = unit:getController()
|
||||
FireAtPoint = {
|
||||
id = 'FireAtPoint',
|
||||
params = {
|
||||
point = {x = unitPos.x, y = unitPos.z},
|
||||
radius = 0.0001,
|
||||
expendQty = shotsToFire,
|
||||
expendQtyEnabled = true,
|
||||
altitude = unitPos.y+unitBarrelHeight +aimUp, --this is a realtive to sea level shot, so we can shoot down
|
||||
alt_type = 0, --0 = sea level, 1 = ground level
|
||||
}
|
||||
}
|
||||
controller:pushTask(FireAtPoint) --FIREEEEEE
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function shots.fireAAA()
|
||||
unit = Unit.getByName(shots.shooterName)
|
||||
target = Unit.getByName(shots.targetName)
|
||||
targetMotionVec = Object.getVelocity(target) --if you don't want to do this i.e. shoot a point send a nil or a vec3 of 0's
|
||||
--local targetMotionVec = nil
|
||||
targetPos = target:getPosition().p
|
||||
shots.aaa(roundVelocity, unit, unitMaxRange, targetPos, shotsToFire,shotDelay, targetMotionVec)
|
||||
end
|
||||
|
||||
--aaa fires almost straight up, no line of sight fakery needed or working out lobbing bullets onto random points
|
||||
--if in range just needs to be told to shoot where the target will be in a few seconds
|
||||
--if out of range, we just need to extrapolate back and fire inside max range and randomise the up and down, then let it miss
|
||||
|
||||
function shots.aaa(v, unit, unitMaxRange, targetPos, shotsToFire,shotDelay, targetMotionVector)
|
||||
local unitPos = unit:getPosition().p
|
||||
local x = mist.utils.get2DDist(unitPos,targetPos) -- horizontal range
|
||||
local x3d = mist.utils.get3DDist(unitPos,targetPos) -- slant range
|
||||
|
||||
if x3d > unitMaxRange then
|
||||
if targetMotionVector == nil then
|
||||
--no moving? nothing to ammend
|
||||
else --work out where target will be when the bullet arrives
|
||||
shotDelay = shotDelay + x3d/(v/2) --time taken to aim and time for bullet to fly to spot long range roughly 50% slowdown
|
||||
newPosition = mist.utils.tableShow(targetMotionVector)
|
||||
targetPos.x = targetPos.x + targetMotionVector.x*shotDelay
|
||||
targetPos.y = targetPos.y + targetMotionVector.y*shotDelay
|
||||
targetPos.z = targetPos.z + targetMotionVector.z*shotDelay
|
||||
end
|
||||
|
||||
difference = mist.vec.sub(targetPos,unitPos)
|
||||
unitVec = mist.vec.getUnitVec(difference)
|
||||
extendPath = mist.vec.scalar_mult(unitVec ,unitMaxRange)
|
||||
targetPos = mist.vec.add(extendPath,unitPos)
|
||||
|
||||
|
||||
local controller = unit:getController()
|
||||
FireAtPoint = {
|
||||
id = 'FireAtPoint',
|
||||
params = {
|
||||
point = {x = targetPos.x, y = targetPos.z},
|
||||
radius = 0.0001,
|
||||
expendQty = shotsToFire,
|
||||
expendQtyEnabled = true,
|
||||
altitude = targetPos.y+math.random(1,500), --this is a realtive to sea level shot, so we can shoot down
|
||||
alt_type = 0, --0 = sea level, 1 = ground level
|
||||
}
|
||||
}
|
||||
controller:pushTask(FireAtPoint) --FIREEEEEE
|
||||
else
|
||||
if targetMotionVector == nil then
|
||||
--no moving? nothing to ammend
|
||||
else --work out where target will be when the bullet arrives
|
||||
shotDelay = shotDelay + x3d/v --time taken to aim and time for bullet to fly to spot
|
||||
newPosition = mist.utils.tableShow(targetMotionVector)
|
||||
targetPos.x = targetPos.x + targetMotionVector.x*shotDelay
|
||||
targetPos.y = targetPos.y + targetMotionVector.y*shotDelay
|
||||
targetPos.z = targetPos.z + targetMotionVector.z*shotDelay
|
||||
end
|
||||
|
||||
local controller = unit:getController()
|
||||
FireAtPoint = {
|
||||
id = 'FireAtPoint',
|
||||
params = {
|
||||
point = {x = targetPos.x, y = targetPos.z},
|
||||
radius = 0.0001,
|
||||
expendQty = shotsToFire,
|
||||
expendQtyEnabled = true,
|
||||
altitude = targetPos.y, --this is a realtive to sea level shot, so we can shoot down
|
||||
alt_type = 0, --0 = sea level, 1 = ground level
|
||||
}
|
||||
}
|
||||
controller:pushTask(FireAtPoint) --FIREEEEEE
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
do
|
||||
longRangeShots = missionCommands.addSubMenu("Firefight")
|
||||
missionCommands.addCommand ("Fire", longRangeShots, shots.vulcan)
|
||||
|
||||
end
|
||||
|
||||
shots.notify("raisedShots.lua ran", 2)
|
||||
540
scripts/samSimulator.lua
Normal file
540
scripts/samSimulator.lua
Normal file
@ -0,0 +1,540 @@
|
||||
--Spawn a SAM integrated with IADS
|
||||
--Spawn a normal SAM
|
||||
--SAM bubble shields
|
||||
|
||||
samSim = {}
|
||||
samSim.samSuffix = 1
|
||||
|
||||
do -- needs to go early on
|
||||
redIADS = SkynetIADS:create('Red')
|
||||
redIADS:setUpdateInterval(5)
|
||||
redIADS:activate()
|
||||
--redIADS:addRadioMenu()
|
||||
end
|
||||
|
||||
function samSim.genSAten() --gens an SA 10 as you can imagine,
|
||||
unit = Unit.getByName("Test")
|
||||
local pointVec3Gl = unit:getPosition().p -- this is just to find where my aircraft is and whack an SA10 below it, lazy not relevant
|
||||
local isHiddenCheck = math.random(100)
|
||||
if isHiddenCheck > 10 then
|
||||
isHidden = false
|
||||
else
|
||||
isHidden = true -- fairly obvious hides from F10 and F7 view
|
||||
end
|
||||
mist.dynAdd(
|
||||
{
|
||||
country = 'USSR',
|
||||
category = 'vehicle',
|
||||
name = "SAM " .. samSim.samSuffix,
|
||||
groupName = "SAM " .. samSim.samSuffix,
|
||||
groupId = 10000+samSim.samSuffix,
|
||||
hidden = isHidden,
|
||||
units =
|
||||
{ [1] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S-300PS 40B6MD sr", --search radar needs to be first always for avoiding a skynet bug
|
||||
["y"] = pointVec3Gl.z + 50,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S-300PS 40B6M tr",
|
||||
["y"] = pointVec3Gl.z,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 4.7123889803847,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [2]
|
||||
|
||||
[3] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S-300PS 54K6 cp",
|
||||
["y"] = pointVec3Gl.z + 100,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 3.1415926535898,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [3]
|
||||
[4] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S-300PS 64H6E sr",
|
||||
["y"] = pointVec3Gl.z - 50,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 3.1415926535898,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [4]
|
||||
[5] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S-300PS 5P85C ln",
|
||||
["y"] = pointVec3Gl.z +200 ,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 3.1415926535898,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [5]
|
||||
[6] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S-300PS 5P85C ln",
|
||||
["y"] = pointVec3Gl.z -200,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 3.3161255787892,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [6]
|
||||
[7] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S-300PS 5P85C ln",
|
||||
["y"] = pointVec3Gl.z ,
|
||||
["x"] = pointVec3Gl.x + 200,
|
||||
["heading"] = 2.9670597283904,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [7]
|
||||
[8] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Excellent",
|
||||
["type"] = "S-300PS 5P85C ln",
|
||||
["y"] = pointVec3Gl.z,
|
||||
["x"] = pointVec3Gl.x -200,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [8]
|
||||
[9] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "generator_5i57",
|
||||
["y"] = pointVec3Gl.z +200,
|
||||
["x"] = pointVec3Gl.x + 200,
|
||||
["heading"] = 6.1086523819802,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [9]
|
||||
[10] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "ATZ-5",
|
||||
["y"] = pointVec3Gl.z -200,
|
||||
["x"] = pointVec3Gl.x -200,
|
||||
["heading"] = 0.17453292519943,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [10]
|
||||
[11] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "ATZ-5",
|
||||
["y"] = pointVec3Gl.z +550,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [11]
|
||||
[12] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "GAZ-66",
|
||||
["y"] = pointVec3Gl.z +580,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [12]
|
||||
[13] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "ATZ-60_Maz",
|
||||
["y"] = pointVec3Gl.z +600,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [13]
|
||||
[14] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "KAMAZ Truck",
|
||||
["y"] = pointVec3Gl.z +500,
|
||||
["x"] = pointVec3Gl.x + 20,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [14]
|
||||
}, -- end of units
|
||||
} -- end of function
|
||||
)
|
||||
redIADS:addSAMSite("SAM " .. samSim.samSuffix) --skynet bit
|
||||
local detectChance = math.random(50,90)
|
||||
local goLiveRange = math.random(50,90)
|
||||
local harmStop = math.random(2)
|
||||
if harmStop == 1 then
|
||||
harmStopping = true
|
||||
else
|
||||
harmStopping = false
|
||||
end
|
||||
redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setHARMDetectionChance(detectChance) -- doesn't bloody work no idea, don't care want to reinvent this myself
|
||||
redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setGoLiveRangeInPercent(goLiveRange) -- doesn't bloody work no idea, don't care want to reinvent this myself
|
||||
redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setCanEngageHARM(harmStopping) -- doesn't bloody work no idea, don't care want to reinvent this myself
|
||||
|
||||
samSim.samSuffix = samSim.samSuffix + 1
|
||||
end
|
||||
|
||||
function samSim.genSAtwo()
|
||||
unit = Unit.getByName("Test")
|
||||
local pointVec3Gl = unit:getPosition().p -- this is just to find where my aircraft is and whack an SA10 below it, lazy not relevant
|
||||
|
||||
local isHiddenCheck = math.random(100)
|
||||
if isHiddenCheck > 50 then
|
||||
isHidden = false
|
||||
else
|
||||
isHidden = true
|
||||
end
|
||||
|
||||
mist.dynAdd(
|
||||
{
|
||||
country = 'USSR',
|
||||
category = 'vehicle',
|
||||
name = "SAM " .. samSim.samSuffix,
|
||||
groupName = "SAM " .. samSim.samSuffix,
|
||||
groupId = 10000+samSim.samSuffix,
|
||||
hidden = isHidden,
|
||||
units =
|
||||
{
|
||||
[1] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "SNR_75V",
|
||||
["y"] = pointVec3Gl.z,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 4.7123889803847,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [1]
|
||||
[2] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S_75M_Volhov",
|
||||
["y"] = pointVec3Gl.z + 50,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [2]
|
||||
[3] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S_75M_Volhov",
|
||||
["y"] = pointVec3Gl.z + 100,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 3.1415926535898,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [3]
|
||||
[4] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S_75M_Volhov",
|
||||
["y"] = pointVec3Gl.z - 50,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 3.1415926535898,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [4]
|
||||
[5] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S_75M_Volhov",
|
||||
["y"] = pointVec3Gl.z +200 ,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 3.1415926535898,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [5]
|
||||
[6] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "S_75M_Volhov",
|
||||
["y"] = pointVec3Gl.z -200,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 3.3161255787892,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [6]
|
||||
[7] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "SKP-11",
|
||||
["y"] = pointVec3Gl.z ,
|
||||
["x"] = pointVec3Gl.x + 200,
|
||||
["heading"] = 2.9670597283904,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [7]
|
||||
[8] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Excellent",
|
||||
["type"] = "SKP-11",
|
||||
["y"] = pointVec3Gl.z,
|
||||
["x"] = pointVec3Gl.x -200,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [8]
|
||||
[9] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "p-19 s-125 sr",
|
||||
["y"] = pointVec3Gl.z +200,
|
||||
["x"] = pointVec3Gl.x + 200,
|
||||
["heading"] = 6.1086523819802,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [9]
|
||||
[10] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "Ural-4320 APA-5D",
|
||||
["y"] = pointVec3Gl.z -200,
|
||||
["x"] = pointVec3Gl.x -200,
|
||||
["heading"] = 0.17453292519943,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [10]
|
||||
[11] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "ATMZ-5",
|
||||
["y"] = pointVec3Gl.z +550,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [11]
|
||||
[12] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "Ural-4320T",
|
||||
["y"] = pointVec3Gl.z +580,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [12]
|
||||
[13] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "Ural-4320T",
|
||||
["y"] = pointVec3Gl.z +600,
|
||||
["x"] = pointVec3Gl.x,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [13]
|
||||
[14] =
|
||||
{
|
||||
["transportable"] =
|
||||
{
|
||||
["randomTransportable"] = false,
|
||||
}, -- end of ["transportable"]
|
||||
["skill"] = "Random",
|
||||
["type"] = "ATMZ-5",
|
||||
["y"] = pointVec3Gl.z +500,
|
||||
["x"] = pointVec3Gl.x + 20,
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
livery_id = "desert",
|
||||
}, -- end of [14]
|
||||
}, -- end of units
|
||||
} -- end of function
|
||||
)
|
||||
redIADS:addSAMSite("SAM " .. samSim.samSuffix)
|
||||
local detectChance = math.random(75,100)
|
||||
local goLiveRange = math.random(50,90)
|
||||
redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setHARMDetectionChance(detectChance)
|
||||
redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setGoLiveRangeInPercent(goLiveRange)
|
||||
|
||||
samSim.samSuffix = samSim.samSuffix + 1
|
||||
end
|
||||
|
||||
function samSim.genCMD()
|
||||
unit = Unit.getByName("Test")
|
||||
local pointVec3Gl = unit:getPosition().p
|
||||
mist.dynAddStatic(
|
||||
{
|
||||
country = 'USSR',
|
||||
category = 'Fortifications',
|
||||
name = "CMD " .. samSim.samSuffix,
|
||||
type = ".Command Center",
|
||||
x = pointVec3Gl.x,
|
||||
y = pointVec3Gl.z,
|
||||
heading = math.pi*3/2,
|
||||
} -- end of function
|
||||
)
|
||||
nameToAdd = "CMD ".. samSim.samSuffix --.. " " .. "unit1"
|
||||
local commandCenter = StaticObject.getByName(nameToAdd)
|
||||
redIADS:addCommandCenter(commandCenter)
|
||||
redIADS = SkynetIADS:create(nameToAdd)
|
||||
redIADS:activate()
|
||||
samSim.samSuffix = samSim.samSuffix + 1
|
||||
end
|
||||
|
||||
function samSim.genEWR()
|
||||
unit = Unit.getByName("Test")
|
||||
local pointVec3Gl = unit:getPosition().p
|
||||
mist.dynAdd(
|
||||
{
|
||||
country = 'USSR',
|
||||
category = 'vehicle',
|
||||
groupName = "EW " .. samSim.samSuffix,
|
||||
name = "EW " .. samSim.samSuffix,
|
||||
groupId = 20000+samSim.samSuffix,
|
||||
units =
|
||||
{
|
||||
[1] =
|
||||
{
|
||||
["skill"] = "Random",
|
||||
["type"] = "55G6 EWR",
|
||||
["y"] = pointVec3Gl.z,
|
||||
["x"] = pointVec3Gl.x,
|
||||
livery_id = "",
|
||||
["heading"] = 0,
|
||||
["playerCanDrive"] = true,
|
||||
},
|
||||
}, -- end of units
|
||||
} -- end of function
|
||||
)
|
||||
nameToAdd = "EW ".. samSim.samSuffix .. " " .. "unit1" -- oddly this is the unit name not the group, if you don't use this naming convention change it
|
||||
redIADS:addEarlyWarningRadar(nameToAdd)
|
||||
--redIADS:addEarlyWarningRadarsByPrefix("EW")
|
||||
samSim.samSuffix = samSim.samSuffix + 1
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
do
|
||||
samSims = missionCommands.addSubMenu("Sam stuff")
|
||||
missionCommands.addCommand ("Spawn SA 10", samSims, samSim.genSAten)
|
||||
missionCommands.addCommand ("Spawn EWR", samSims, samSim.genEWR)
|
||||
missionCommands.addCommand ("Spawn SA 2", samSims, samSim.genSAtwo)
|
||||
missionCommands.addCommand ("Spawn Command Centre and activate", samSims, samSim.genCMD)
|
||||
end
|
||||
@ -63,11 +63,13 @@ void Aircraft::changeAltitude(wstring change)
|
||||
void Aircraft::setTargetSpeed(double newTargetSpeed) {
|
||||
targetSpeed = newTargetSpeed;
|
||||
addMeasure(L"targetSpeed", json::value(targetSpeed));
|
||||
goToDestination();
|
||||
if (activeDestination != NULL)
|
||||
goToDestination();
|
||||
}
|
||||
|
||||
void Aircraft::setTargetAltitude(double newTargetAltitude) {
|
||||
targetAltitude = newTargetAltitude;
|
||||
addMeasure(L"targetAltitude", json::value(targetAltitude));
|
||||
goToDestination();
|
||||
if (activeDestination != NULL)
|
||||
goToDestination();
|
||||
}
|
||||
@ -149,7 +149,7 @@ bool AirUnit::updateActivePath(bool looping)
|
||||
/* Push the next destination in the queue to the front */
|
||||
if (looping)
|
||||
pushActivePathBack(activePath.front());
|
||||
activePath.pop_front();
|
||||
popActivePathFront();
|
||||
log(unitName + L" active path front popped");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -179,7 +179,35 @@ void Server::handle_put(http_request request)
|
||||
|
||||
void Server::task()
|
||||
{
|
||||
http_listener listener(wstring(REST_ADDRESS) + L"/" + wstring(REST_URI));
|
||||
wstring address = wstring(REST_ADDRESS);
|
||||
wstring modLocation;
|
||||
char* buf = nullptr;
|
||||
size_t sz = 0;
|
||||
if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr)
|
||||
{
|
||||
std::ifstream ifstream(string(buf) + "\\olympus.json");
|
||||
std::stringstream ss;
|
||||
ss << ifstream.rdbuf();
|
||||
std::error_code errorCode;
|
||||
json::value config = json::value::parse(to_wstring(ss.str()), errorCode);
|
||||
if (config.is_object() && config.has_object_field(L"server") &&
|
||||
config[L"server"].has_string_field(L"address") && config[L"server"].has_number_field(L"port"))
|
||||
{
|
||||
address = L"http://" + config[L"server"][L"address"].as_string() + L":" + to_wstring(config[L"server"][L"port"].as_number().to_int32());
|
||||
log(L"Starting server on " + address);
|
||||
}
|
||||
else
|
||||
{
|
||||
log(L"Error reading configuration file. Starting server on " + address);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
log(L"DCSOLYMPUS_PATH environment variable is missing, starting server on " + address);
|
||||
}
|
||||
|
||||
http_listener listener(address + L"/" + wstring(REST_URI));
|
||||
|
||||
std::function<void(http_request)> handle_options = std::bind(&Server::handle_options, this, std::placeholders::_1);
|
||||
std::function<void(http_request)> handle_get = std::bind(&Server::handle_get, this, std::placeholders::_1);
|
||||
|
||||
@ -201,7 +201,6 @@ void Unit::popActivePathFront()
|
||||
setActivePath(path);
|
||||
}
|
||||
|
||||
|
||||
void Unit::setCoalitionID(int newCoalitionID)
|
||||
{
|
||||
if (newCoalitionID == 0)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user