Compare commits

..

1 Commits

Author SHA1 Message Date
zhexu14
94c68dd9f0 Update requirements.txt to latest pydcs version 2025-05-02 21:15:15 +10:00
67 changed files with 848 additions and 2114 deletions

View File

@@ -4,18 +4,11 @@ Saves from 13.x are not compatible with 14.0.0.
## Features/Improvements ## Features/Improvements
* **[Engine]** Support for DCS 2.9.21. * **[Engine]** Support for DCS 2.9.13.6818.
* **[Engine]** Support for MiG-29 Fulcrum (full fidelity version).
* **[Engine]** Support for F-14A-135-GR Early.
* **[Mods]** A4EC mod version updated to 2.3.
* **[UI]** Allow saving after fast forwarding manually with sim speed controls (--show-sim-speed-controls option).
* **[UI]** Add new option to fast forward until player is at the IP.
## Fixes ## Fixes
* **[Campaign]** Units are restored to full health when repaired.
* **[UI]** Air Wing and Transfers buttons disabled when no game is loaded as pressing them without a game loaded resulted in a crash. * **[UI]** Air Wing and Transfers buttons disabled when no game is loaded as pressing them without a game loaded resulted in a crash.
* **[UI]** A package is cancelled (deleted) when the last flight in the package is cancelled instead of showing "No mission".
# 13.0.0 # 13.0.0

571
client/package-lock.json generated
View File

@@ -18,7 +18,7 @@
"@types/react": "^18.0.21", "@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@types/react-redux": "^7.1.24", "@types/react-redux": "^7.1.24",
"axios": "^1.12.1", "axios": "^1.8.3",
"electron-window-state": "^5.0.3", "electron-window-state": "^5.0.3",
"esri-leaflet": "^3.0.8", "esri-leaflet": "^3.0.8",
"leaflet": "^1.9.2", "leaflet": "^1.9.2",
@@ -38,7 +38,7 @@
"@types/leaflet": "^1.8.0", "@types/leaflet": "^1.8.0",
"@types/redux-logger": "^3.0.9", "@types/redux-logger": "^3.0.9",
"@types/websocket": "^1.0.5", "@types/websocket": "^1.0.5",
"electron": "^35.7.5", "electron": "^22.3.25",
"electron-is-dev": "^2.0.0", "electron-is-dev": "^2.0.0",
"generate-license-file": "^2.0.0", "generate-license-file": "^2.0.0",
"jest-transform-stub": "^2.0.0", "jest-transform-stub": "^2.0.0",
@@ -4909,12 +4909,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.19.113", "version": "18.8.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.113.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz",
"integrity": "sha512-TmSTE9vyebJ9vSEiU+P+0Sp4F5tMgjiEOZaQUW6wA3ODvi6uBgkHQ+EsIu0pbiKvf9QHEvyRCiaz03rV0b+IaA==", "integrity": "sha512-0os9vz6BpGwxGe9LOhgP/ncvYN5Tx1fNcd2TM3rD/aCGBkysb+ZWpXEocG24h6ZzOi13+VB8HndAQFezsSOw1w=="
"dependencies": {
"undici-types": "~5.26.4"
}
}, },
"node_modules/@types/parse-json": { "node_modules/@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -6097,24 +6094,23 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.12.1", "version": "1.8.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz",
"integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==", "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==",
"license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
"form-data": "^4.0.4", "form-data": "^4.0.0",
"proxy-from-env": "^1.1.0" "proxy-from-env": "^1.1.0"
} }
}, },
"node_modules/axios/node_modules/form-data": { "node_modules/axios/node_modules/form-data": {
"version": "4.0.4", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
@@ -6569,6 +6565,15 @@
"npm": "1.2.8000 || >= 1.4.16" "npm": "1.2.8000 || >= 1.4.16"
} }
}, },
"node_modules/body-parser/node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
},
"node_modules/body-parser/node_modules/debug": { "node_modules/body-parser/node_modules/debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -6758,9 +6763,9 @@
} }
}, },
"node_modules/bytes": { "node_modules/bytes": {
"version": "3.1.2", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 0.8" "node": ">= 0.8"
@@ -6827,18 +6832,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-me-maybe": { "node_modules/call-me-maybe": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
@@ -7223,17 +7216,17 @@
} }
}, },
"node_modules/compression": { "node_modules/compression": {
"version": "1.8.1", "version": "1.7.4",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
"integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"bytes": "3.1.2", "accepts": "~1.3.5",
"compressible": "~2.0.18", "bytes": "3.0.0",
"compressible": "~2.0.16",
"debug": "2.6.9", "debug": "2.6.9",
"negotiator": "~0.6.4", "on-headers": "~1.0.2",
"on-headers": "~1.1.0", "safe-buffer": "5.1.2",
"safe-buffer": "5.2.1",
"vary": "~1.1.2" "vary": "~1.1.2"
}, },
"engines": { "engines": {
@@ -7255,35 +7248,6 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true "dev": true
}, },
"node_modules/compression/node_modules/negotiator": {
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
"integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/compression/node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -8395,19 +8359,6 @@
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
"dev": true "dev": true
}, },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/duplexer": { "node_modules/duplexer": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
@@ -8442,14 +8393,14 @@
} }
}, },
"node_modules/electron": { "node_modules/electron": {
"version": "35.7.5", "version": "22.3.25",
"resolved": "https://registry.npmjs.org/electron/-/electron-35.7.5.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-22.3.25.tgz",
"integrity": "sha512-dnL+JvLraKZl7iusXTVTGYs10TKfzUi30uEDTqsmTm0guN9V2tbOjTzyIZbh9n3ygUjgEYyo+igAwMRXIi3IPw==", "integrity": "sha512-AjrP7bebMs/IPsgmyowptbA7jycTkrJC7jLZTb5JoH30PkBC6pZx/7XQ0aDok82SsmSiF4UJDOg+HoLrEBiqmg==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@electron/get": "^2.0.0", "@electron/get": "^2.0.0",
"@types/node": "^22.7.7", "@types/node": "^16.11.26",
"extract-zip": "^2.0.1" "extract-zip": "^2.0.1"
}, },
"bin": { "bin": {
@@ -8495,18 +8446,9 @@
} }
}, },
"node_modules/electron/node_modules/@types/node": { "node_modules/electron/node_modules/@types/node": {
"version": "22.18.0", "version": "16.11.64",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.64.tgz",
"integrity": "sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==", "integrity": "sha512-z5hPTlVFzNwtJ2LNozTpJcD1Cu44c4LNuzaq1mwxmiHWQh2ULdR6Vjwo1UGldzRpzL0yUEdZddnfqGW2G70z6Q==",
"dev": true,
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/electron/node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true "dev": true
}, },
"node_modules/emittery": { "node_modules/emittery": {
@@ -8654,9 +8596,13 @@
} }
}, },
"node_modules/es-define-property": { "node_modules/es-define-property": {
"version": "1.0.1", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.2.4"
},
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
} }
@@ -8665,6 +8611,7 @@
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
} }
@@ -8675,31 +8622,6 @@
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
"dev": true "dev": true
}, },
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-shim-unscopables": { "node_modules/es-shim-unscopables": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
@@ -10259,16 +10181,14 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "3.0.4", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
"integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12"
"hasown": "^2.0.2",
"mime-types": "^2.1.35"
}, },
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
@@ -10349,6 +10269,7 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@@ -10428,20 +10349,16 @@
} }
}, },
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.3.0", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2", "function-bind": "^1.1.2",
"get-proto": "^1.0.1", "has-proto": "^1.0.1",
"gopd": "^1.2.0", "has-symbols": "^1.0.3",
"has-symbols": "^1.1.0", "hasown": "^2.0.0"
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
}, },
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@@ -10465,18 +10382,6 @@
"node": ">=8.0.0" "node": ">=8.0.0"
} }
}, },
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/get-stream": { "node_modules/get-stream": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -10650,11 +10555,12 @@
} }
}, },
"node_modules/gopd": { "node_modules/gopd": {
"version": "1.2.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"engines": { "dev": true,
"node": ">= 0.4" "dependencies": {
"get-intrinsic": "^1.1.3"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@@ -10773,10 +10679,23 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/has-proto": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": { "node_modules/has-symbols": {
"version": "1.1.0", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
}, },
@@ -10785,11 +10704,12 @@
} }
}, },
"node_modules/has-tostringtag": { "node_modules/has-tostringtag": {
"version": "1.0.2", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dev": true,
"dependencies": { "dependencies": {
"has-symbols": "^1.0.3" "has-symbols": "^1.0.2"
}, },
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@@ -10802,6 +10722,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"dependencies": { "dependencies": {
"function-bind": "^1.1.2" "function-bind": "^1.1.2"
}, },
@@ -14524,14 +14445,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/mdn-data": { "node_modules/mdn-data": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
@@ -14622,19 +14535,19 @@
} }
}, },
"node_modules/mime-db": { "node_modules/mime-db": {
"version": "1.52.0", "version": "1.51.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/mime-types": { "node_modules/mime-types": {
"version": "2.1.35", "version": "2.1.34",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
"dependencies": { "dependencies": {
"mime-db": "1.52.0" "mime-db": "1.51.0"
}, },
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
@@ -15495,9 +15408,9 @@
} }
}, },
"node_modules/on-headers": { "node_modules/on-headers": {
"version": "1.1.0", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 0.8" "node": ">= 0.8"
@@ -17511,6 +17424,15 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/raw-body/node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true,
"engines": {
"node": ">= 0.8"
}
},
"node_modules/raw-body/node_modules/iconv-lite": { "node_modules/raw-body/node_modules/iconv-lite": {
"version": "0.4.24", "version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -20254,11 +20176,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
},
"node_modules/unicode-canonical-property-names-ecmascript": { "node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@@ -20887,16 +20804,16 @@
} }
}, },
"node_modules/webpack-dev-server/node_modules/ws": { "node_modules/webpack-dev-server/node_modules/ws": {
"version": "8.18.3", "version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"bufferutil": "^4.0.1", "bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2" "utf-8-validate": "^5.0.2"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"bufferutil": { "bufferutil": {
@@ -21496,9 +21413,9 @@
} }
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "7.5.10", "version": "7.5.7",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=8.3.0" "node": ">=8.3.0"
@@ -25227,12 +25144,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "18.19.113", "version": "18.8.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.113.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz",
"integrity": "sha512-TmSTE9vyebJ9vSEiU+P+0Sp4F5tMgjiEOZaQUW6wA3ODvi6uBgkHQ+EsIu0pbiKvf9QHEvyRCiaz03rV0b+IaA==", "integrity": "sha512-0os9vz6BpGwxGe9LOhgP/ncvYN5Tx1fNcd2TM3rD/aCGBkysb+ZWpXEocG24h6ZzOi13+VB8HndAQFezsSOw1w=="
"requires": {
"undici-types": "~5.26.4"
}
}, },
"@types/parse-json": { "@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -26145,24 +26059,22 @@
"dev": true "dev": true
}, },
"axios": { "axios": {
"version": "1.12.1", "version": "1.8.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz",
"integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==", "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==",
"requires": { "requires": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
"form-data": "^4.0.4", "form-data": "^4.0.0",
"proxy-from-env": "^1.1.0" "proxy-from-env": "^1.1.0"
}, },
"dependencies": { "dependencies": {
"form-data": { "form-data": {
"version": "4.0.4", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": { "requires": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
} }
} }
@@ -26515,6 +26427,12 @@
"unpipe": "1.0.0" "unpipe": "1.0.0"
}, },
"dependencies": { "dependencies": {
"bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true
},
"debug": { "debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -26654,9 +26572,9 @@
"dev": true "dev": true
}, },
"bytes": { "bytes": {
"version": "3.1.2", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
"dev": true "dev": true
}, },
"cacheable-lookup": { "cacheable-lookup": {
@@ -26704,15 +26622,6 @@
"set-function-length": "^1.2.1" "set-function-length": "^1.2.1"
} }
}, },
"call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"requires": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
}
},
"call-me-maybe": { "call-me-maybe": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
@@ -27003,17 +26912,17 @@
} }
}, },
"compression": { "compression": {
"version": "1.8.1", "version": "1.7.4",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
"integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"bytes": "3.1.2", "accepts": "~1.3.5",
"compressible": "~2.0.18", "bytes": "3.0.0",
"compressible": "~2.0.16",
"debug": "2.6.9", "debug": "2.6.9",
"negotiator": "~0.6.4", "on-headers": "~1.0.2",
"on-headers": "~1.1.0", "safe-buffer": "5.1.2",
"safe-buffer": "5.2.1",
"vary": "~1.1.2" "vary": "~1.1.2"
}, },
"dependencies": { "dependencies": {
@@ -27031,18 +26940,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true "dev": true
},
"negotiator": {
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
"integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
"dev": true
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true
} }
} }
}, },
@@ -27863,16 +27760,6 @@
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
"dev": true "dev": true
}, },
"dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"requires": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
}
},
"duplexer": { "duplexer": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
@@ -27901,29 +27788,20 @@
} }
}, },
"electron": { "electron": {
"version": "35.7.5", "version": "22.3.25",
"resolved": "https://registry.npmjs.org/electron/-/electron-35.7.5.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-22.3.25.tgz",
"integrity": "sha512-dnL+JvLraKZl7iusXTVTGYs10TKfzUi30uEDTqsmTm0guN9V2tbOjTzyIZbh9n3ygUjgEYyo+igAwMRXIi3IPw==", "integrity": "sha512-AjrP7bebMs/IPsgmyowptbA7jycTkrJC7jLZTb5JoH30PkBC6pZx/7XQ0aDok82SsmSiF4UJDOg+HoLrEBiqmg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@electron/get": "^2.0.0", "@electron/get": "^2.0.0",
"@types/node": "^22.7.7", "@types/node": "^16.11.26",
"extract-zip": "^2.0.1" "extract-zip": "^2.0.1"
}, },
"dependencies": { "dependencies": {
"@types/node": { "@types/node": {
"version": "22.18.0", "version": "16.11.64",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.64.tgz",
"integrity": "sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==", "integrity": "sha512-z5hPTlVFzNwtJ2LNozTpJcD1Cu44c4LNuzaq1mwxmiHWQh2ULdR6Vjwo1UGldzRpzL0yUEdZddnfqGW2G70z6Q==",
"dev": true,
"requires": {
"undici-types": "~6.21.0"
}
},
"undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true "dev": true
} }
} }
@@ -28074,14 +27952,19 @@
} }
}, },
"es-define-property": { "es-define-property": {
"version": "1.0.1", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"dev": true,
"requires": {
"get-intrinsic": "^1.2.4"
}
}, },
"es-errors": { "es-errors": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true
}, },
"es-module-lexer": { "es-module-lexer": {
"version": "1.5.4", "version": "1.5.4",
@@ -28089,25 +27972,6 @@
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
"dev": true "dev": true
}, },
"es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"requires": {
"es-errors": "^1.3.0"
}
},
"es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"requires": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
}
},
"es-shim-unscopables": { "es-shim-unscopables": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
@@ -29266,16 +29130,14 @@
} }
}, },
"form-data": { "form-data": {
"version": "3.0.4", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
"integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
"dev": true, "dev": true,
"requires": { "requires": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12"
"hasown": "^2.0.2",
"mime-types": "^2.1.35"
} }
}, },
"forwarded": { "forwarded": {
@@ -29329,7 +29191,8 @@
"function-bind": { "function-bind": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true
}, },
"function.prototype.name": { "function.prototype.name": {
"version": "1.1.5", "version": "1.1.5",
@@ -29388,20 +29251,16 @@
"dev": true "dev": true
}, },
"get-intrinsic": { "get-intrinsic": {
"version": "1.3.0", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dev": true,
"requires": { "requires": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2", "function-bind": "^1.1.2",
"get-proto": "^1.0.1", "has-proto": "^1.0.1",
"gopd": "^1.2.0", "has-symbols": "^1.0.3",
"has-symbols": "^1.1.0", "hasown": "^2.0.0"
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
} }
}, },
"get-own-enumerable-property-symbols": { "get-own-enumerable-property-symbols": {
@@ -29416,15 +29275,6 @@
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true "dev": true
}, },
"get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"requires": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
}
},
"get-stream": { "get-stream": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -29552,9 +29402,13 @@
} }
}, },
"gopd": { "gopd": {
"version": "1.2.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dev": true,
"requires": {
"get-intrinsic": "^1.1.3"
}
}, },
"got": { "got": {
"version": "11.8.6", "version": "11.8.6",
@@ -29642,23 +29496,32 @@
"es-define-property": "^1.0.0" "es-define-property": "^1.0.0"
} }
}, },
"has-proto": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true
},
"has-symbols": { "has-symbols": {
"version": "1.1.0", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true
}, },
"has-tostringtag": { "has-tostringtag": {
"version": "1.0.2", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dev": true,
"requires": { "requires": {
"has-symbols": "^1.0.3" "has-symbols": "^1.0.2"
} }
}, },
"hasown": { "hasown": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"requires": { "requires": {
"function-bind": "^1.1.2" "function-bind": "^1.1.2"
} }
@@ -32445,11 +32308,6 @@
} }
} }
}, },
"math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="
},
"mdn-data": { "mdn-data": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
@@ -32516,16 +32374,16 @@
"dev": true "dev": true
}, },
"mime-db": { "mime-db": {
"version": "1.52.0", "version": "1.51.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
}, },
"mime-types": { "mime-types": {
"version": "2.1.35", "version": "2.1.34",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
"requires": { "requires": {
"mime-db": "1.52.0" "mime-db": "1.51.0"
} }
}, },
"mimic-fn": { "mimic-fn": {
@@ -33165,9 +33023,9 @@
} }
}, },
"on-headers": { "on-headers": {
"version": "1.1.0", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
"dev": true "dev": true
}, },
"once": { "once": {
@@ -34549,6 +34407,12 @@
"unpipe": "1.0.0" "unpipe": "1.0.0"
}, },
"dependencies": { "dependencies": {
"bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true
},
"iconv-lite": { "iconv-lite": {
"version": "0.4.24", "version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -36660,11 +36524,6 @@
"which-boxed-primitive": "^1.0.2" "which-boxed-primitive": "^1.0.2"
} }
}, },
"undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
},
"unicode-canonical-property-names-ecmascript": { "unicode-canonical-property-names-ecmascript": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@@ -37154,9 +37013,9 @@
} }
}, },
"ws": { "ws": {
"version": "8.18.3", "version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"dev": true, "dev": true,
"requires": {} "requires": {}
} }
@@ -37651,9 +37510,9 @@
} }
}, },
"ws": { "ws": {
"version": "7.5.10", "version": "7.5.7",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },

View File

@@ -15,7 +15,7 @@
"@types/react": "^18.0.21", "@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@types/react-redux": "^7.1.24", "@types/react-redux": "^7.1.24",
"axios": "^1.12.1", "axios": "^1.8.3",
"electron-window-state": "^5.0.3", "electron-window-state": "^5.0.3",
"esri-leaflet": "^3.0.8", "esri-leaflet": "^3.0.8",
"leaflet": "^1.9.2", "leaflet": "^1.9.2",
@@ -66,7 +66,7 @@
"@types/leaflet": "^1.8.0", "@types/leaflet": "^1.8.0",
"@types/redux-logger": "^3.0.9", "@types/redux-logger": "^3.0.9",
"@types/websocket": "^1.0.5", "@types/websocket": "^1.0.5",
"electron": "^35.7.5", "electron": "^22.3.25",
"electron-is-dev": "^2.0.0", "electron-is-dev": "^2.0.0",
"generate-license-file": "^2.0.0", "generate-license-file": "^2.0.0",
"jest-transform-stub": "^2.0.0", "jest-transform-stub": "^2.0.0",

View File

@@ -12,7 +12,6 @@ from .flightmembers import FlightMembers
from .flightroster import FlightRoster from .flightroster import FlightRoster
from .flightstate import FlightState, Navigating, Uninitialized from .flightstate import FlightState, Navigating, Uninitialized
from .flightstate.killed import Killed from .flightstate.killed import Killed
from .flighttype import FlightType
from ..sidc import ( from ..sidc import (
Entity, Entity,
SidcDescribable, SidcDescribable,
@@ -32,6 +31,7 @@ if TYPE_CHECKING:
from game.data.weapons import WeaponType from game.data.weapons import WeaponType
from .flightmember import FlightMember from .flightmember import FlightMember
from .flightplans.flightplan import FlightPlan from .flightplans.flightplan import FlightPlan
from .flighttype import FlightType
from .flightwaypoint import FlightWaypoint from .flightwaypoint import FlightWaypoint
from .package import Package from .package import Package
from .starttype import StartType from .starttype import StartType
@@ -58,8 +58,7 @@ class Flight(SidcDescribable):
self.coalition = squadron.coalition self.coalition = squadron.coalition
self.squadron = squadron self.squadron = squadron
self.flight_type = flight_type self.flight_type = flight_type
if flight_type != FlightType.IDLE: self.squadron.claim_inventory(count)
self.squadron.claim_inventory(count)
if roster is None: if roster is None:
self.roster = FlightMembers(self, initial_size=count) self.roster = FlightMembers(self, initial_size=count)
else: else:
@@ -110,6 +109,19 @@ class Flight(SidcDescribable):
waypoint.actions.clear() waypoint.actions.clear()
waypoint.options.clear() waypoint.options.clear()
def __getstate__(self) -> dict[str, Any]:
state = self.__dict__.copy()
# Avoid persisting the flight state since that's not (currently) used outside
# mission generation. This is a bit of a hack for the moment and in the future
# we will need to persist the flight state, but for now keep it out of save
# compat (it also contains a generator that cannot be pickled).
del state["state"]
return state
def __setstate__(self, state: dict[str, Any]) -> None:
state["state"] = Uninitialized(self, state["squadron"].settings)
self.__dict__.update(state)
@property @property
def blue(self) -> bool: def blue(self) -> bool:
return self.squadron.player return self.squadron.player

View File

@@ -69,15 +69,6 @@ class FlightMembers(IFlightRoster):
self.flight.squadron.return_pilot(current_pilot) self.flight.squadron.return_pilot(current_pilot)
self.members[index].pilot = pilot self.members[index].pilot = pilot
def remove_pilot(self, pilot: Pilot) -> None:
for i, member in enumerate(self.members):
if member.pilot is not None and member.pilot.name == pilot.name:
self.members.pop(i)
if (code := member.tgp_laser_code) is not None:
code.release()
return
raise ValueError(f"Pilot {pilot.name} not a member")
def clear(self) -> None: def clear(self) -> None:
self.flight.squadron.return_pilots( self.flight.squadron.return_pilots(
[p for p in self.iter_pilots() if p is not None] [p for p in self.iter_pilots() if p is not None]

View File

@@ -12,7 +12,7 @@ from game.utils import Distance, Heading, Speed, feet, knots, meters, nautical_m
class AewcFlightPlan(PatrollingFlightPlan[PatrollingLayout]): class AewcFlightPlan(PatrollingFlightPlan[PatrollingLayout]):
@property @property
def patrol_duration(self) -> timedelta: def patrol_duration(self) -> timedelta:
return self.flight.coalition.doctrine.aewc.duration return timedelta(hours=4)
@property @property
def patrol_speed(self) -> Speed: def patrol_speed(self) -> Speed:

View File

@@ -64,7 +64,6 @@ class FlightPlanBuilderTypes:
FlightType.TRANSPORT: AirliftFlightPlan.builder_type(), FlightType.TRANSPORT: AirliftFlightPlan.builder_type(),
FlightType.FERRY: FerryFlightPlan.builder_type(), FlightType.FERRY: FerryFlightPlan.builder_type(),
FlightType.AIR_ASSAULT: AirAssaultFlightPlan.builder_type(), FlightType.AIR_ASSAULT: AirAssaultFlightPlan.builder_type(),
FlightType.IDLE: BarCapFlightPlan.builder_type(),
} }
try: try:
return builder_dict[flight.flight_type] return builder_dict[flight.flight_type]

View File

@@ -21,14 +21,8 @@ class FlightState(ABC):
self.settings = settings self.settings = settings
self.avoid_further_combat = False self.avoid_further_combat = False
def initialize(self, now: datetime) -> None: def reinitialize(self, now: datetime) -> None:
from game.ato.flightstate import Uninitialized, WaitingForStart from game.ato.flightstate import WaitingForStart
# Flight objects are created with Uninitialized state. However when the simulation runs
# the flight state changes and may be serialized. We only want to initialize the state
# for newly created flights and not ones deserialized from a save file.
if type(self.flight.state) != Uninitialized:
return
if self.flight.flight_plan.startup_time() <= now: if self.flight.flight_plan.startup_time() <= now:
self._set_active_flight_state(now) self._set_active_flight_state(now)

View File

@@ -3,7 +3,6 @@ from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from collections import deque from collections import deque
from datetime import datetime, timedelta from datetime import datetime, timedelta
import logging
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from dcs import Point from dcs import Point
@@ -14,7 +13,6 @@ from game.ato.flightstate.flightstate import FlightState
from game.ato.flightwaypoint import FlightWaypoint from game.ato.flightwaypoint import FlightWaypoint
from game.ato.flightwaypointtype import FlightWaypointType from game.ato.flightwaypointtype import FlightWaypointType
from game.ato.starttype import StartType from game.ato.starttype import StartType
from game.settings.settings import FastForwardStopCondition
from game.utils import Distance, LBS_TO_KG, Speed, pairwise from game.utils import Distance, LBS_TO_KG, Speed, pairwise
if TYPE_CHECKING: if TYPE_CHECKING:
@@ -166,17 +164,3 @@ class InFlight(FlightState, ABC):
@property @property
def spawn_type(self) -> StartType: def spawn_type(self) -> StartType:
return StartType.IN_FLIGHT return StartType.IN_FLIGHT
def should_halt_sim(self) -> bool:
if (
self.flight.client_count > 0
and self.settings.fast_forward_stop_condition
== FastForwardStopCondition.PLAYER_AT_IP
and self.is_at_ip
):
logging.info(
f"Interrupting simulation because {self.flight} has players and has "
"reached IP"
)
return True
return False

View File

@@ -20,7 +20,7 @@ class Uninitialized(FlightState):
def on_game_tick( def on_game_tick(
self, events: GameUpdateEvents, time: datetime, duration: timedelta self, events: GameUpdateEvents, time: datetime, duration: timedelta
) -> None: ) -> None:
self.initialize(time) self.reinitialize(time)
self.flight.state.on_game_tick(events, time, duration) self.flight.state.on_game_tick(events, time, duration)
@property @property

View File

@@ -57,7 +57,6 @@ class FlightType(Enum):
REFUELING = "Refueling" REFUELING = "Refueling"
FERRY = "Ferry" FERRY = "Ferry"
AIR_ASSAULT = "Air Assault" AIR_ASSAULT = "Air Assault"
IDLE = "Idle"
def __str__(self) -> str: def __str__(self) -> str:
return self.value return self.value

View File

@@ -47,17 +47,6 @@ class MissionScheduler:
margin=5 * 60, margin=5 * 60,
) )
for package in self.coalition.ato.packages: for package in self.coalition.ato.packages:
if package.time_over_target > datetime.min:
if package.primary_task in dca_types:
if (
package.mission_departure_time is not None
and package.mission_departure_time
> previous_cap_end_time[package.target]
):
previous_cap_end_time[package.target] = (
package.mission_departure_time
)
continue # If package already has TOT, leave it.
tot = TotEstimator(package).earliest_tot(now) tot = TotEstimator(package).earliest_tot(now)
if package.primary_task in dca_types: if package.primary_task in dca_types:
previous_end_time = previous_cap_end_time[package.target] previous_end_time = previous_cap_end_time[package.target]

View File

@@ -24,7 +24,6 @@ from game.theater.theatergroundobject import (
VehicleGroupGroundObject, VehicleGroupGroundObject,
) )
from game.threatzones import ThreatZones from game.threatzones import ThreatZones
from game.ato.flighttype import FlightType
if TYPE_CHECKING: if TYPE_CHECKING:
from game import Game from game import Game
@@ -78,8 +77,7 @@ class TheaterState(WorldState["TheaterState"]):
self.threatening_air_defenses.remove(target) self.threatening_air_defenses.remove(target)
if target in self.detecting_air_defenses: if target in self.detecting_air_defenses:
self.detecting_air_defenses.remove(target) self.detecting_air_defenses.remove(target)
if target in self.enemy_air_defenses: self.enemy_air_defenses.remove(target)
self.enemy_air_defenses.remove(target)
self._rebuild_threat_zones() self._rebuild_threat_zones()
def eliminate_ship(self, target: NavalGroundObject) -> None: def eliminate_ship(self, target: NavalGroundObject) -> None:
@@ -87,8 +85,7 @@ class TheaterState(WorldState["TheaterState"]):
self.threatening_air_defenses.remove(target) self.threatening_air_defenses.remove(target)
if target in self.detecting_air_defenses: if target in self.detecting_air_defenses:
self.detecting_air_defenses.remove(target) self.detecting_air_defenses.remove(target)
if target in self.enemy_ships: self.enemy_ships.remove(target)
self.enemy_ships.remove(target)
self._rebuild_threat_zones() self._rebuild_threat_zones()
def has_battle_position(self, target: VehicleGroupGroundObject) -> bool: def has_battle_position(self, target: VehicleGroupGroundObject) -> bool:
@@ -158,16 +155,21 @@ class TheaterState(WorldState["TheaterState"]):
tracer, tracer,
) )
# Plan enough rounds of CAP that the target has coverage over the expected
# mission duration.
mission_duration = game.settings.desired_player_mission_duration.total_seconds()
barcap_duration = coalition.doctrine.cap.duration.total_seconds()
barcap_rounds = math.ceil(mission_duration / barcap_duration)
refueling_targets: list[MissionTarget] = [] refueling_targets: list[MissionTarget] = []
theater_refuling_point = finder.preferred_theater_refueling_control_point() theater_refuling_point = finder.preferred_theater_refueling_control_point()
if theater_refuling_point is not None: if theater_refuling_point is not None:
refueling_targets.append(theater_refuling_point) refueling_targets.append(theater_refuling_point)
theater_state = TheaterState( return TheaterState(
context=context, context=context,
barcaps_needed={ barcaps_needed={
cp: cls._barcap_rounds(game, player, now, cp) cp: barcap_rounds for cp in finder.vulnerable_control_points()
for cp in finder.vulnerable_control_points()
}, },
active_front_lines=list(finder.front_lines()), active_front_lines=list(finder.front_lines()),
front_line_stances={f: None for f in finder.front_lines()}, front_line_stances={f: None for f in finder.front_lines()},
@@ -189,62 +191,3 @@ class TheaterState(WorldState["TheaterState"]):
enemy_barcaps=list(game.theater.control_points_for(not player)), enemy_barcaps=list(game.theater.control_points_for(not player)),
threat_zones=game.threat_zone_for(not player), threat_zones=game.threat_zone_for(not player),
) )
# Look through packages already planned in the ATO and eliminate from the
# list of targets.
for package in coalition.ato.packages:
if isinstance(package.target, NavalGroundObject):
theater_state.eliminate_ship(package.target)
if package.primary_task == FlightType.BAI and isinstance(
package.target, VehicleGroupGroundObject
):
theater_state.eliminate_battle_position(package.target)
if isinstance(package.target, IadsGroundObject):
theater_state.eliminate_air_defense(package.target)
if (
package.primary_task == FlightType.STRIKE
and isinstance(package.target, TheaterGroundObject)
and package.target in theater_state.strike_targets
):
theater_state.strike_targets.remove(package.target)
if package.primary_task == FlightType.AEWC:
# If a planned AEWC mission covers the target beyond the planned mission duration, it can safely be removed
if (
package.time_over_target + coalition.doctrine.aewc.duration
> now + game.settings.desired_player_mission_duration
) and package.target in theater_state.aewc_targets:
theater_state.aewc_targets.remove(package.target)
if (
package.primary_task
in (
FlightType.OCA_AIRCRAFT,
FlightType.OCA_RUNWAY,
)
and isinstance(package.target, ControlPoint)
and package.target in theater_state.oca_targets
):
theater_state.oca_targets.remove(package.target)
return theater_state
@classmethod
def _barcap_rounds(
cls, game: Game, player: bool, now: datetime, control_point: ControlPoint
) -> int:
"""Calculate number of additional rounds of CAP required to cover mission duration."""
coalition = game.coalition_for(player)
# Look through ATO for any existing planned CAP missions and calculate last planned CAP end
planned_cap_coverage_end_time = now
for package in coalition.ato.packages:
if package.target == control_point:
cap_end_time = (
package.time_over_target + coalition.doctrine.cap.duration
)
if cap_end_time > planned_cap_coverage_end_time:
planned_cap_coverage_end_time = cap_end_time
# When mission is expected to finish
mission_end_time = now + game.settings.desired_player_mission_duration
return math.ceil(
(mission_end_time - planned_cap_coverage_end_time).total_seconds()
/ coalition.doctrine.cap.duration.total_seconds()
)

View File

@@ -52,16 +52,6 @@ class Helicopter:
) )
@dataclass
class Aewc:
#: The duration that AEWC flights will remain on-station
duration: timedelta
@staticmethod
def from_dict(data: dict[str, Any]) -> Aewc:
return Aewc(duration=timedelta(minutes=data["duration_minutes"]))
@dataclass @dataclass
class Cas: class Cas:
#: The duration that CAP flights will remain on-station. #: The duration that CAP flights will remain on-station.
@@ -179,9 +169,6 @@ class Doctrine:
#: Helicopter specific doctrines. #: Helicopter specific doctrines.
helicopter: Helicopter helicopter: Helicopter
#: Doctrine for AEWC missions.
aewc: Aewc
#: Doctrine for CAS missions. #: Doctrine for CAS missions.
cas: Cas cas: Cas
@@ -251,7 +238,6 @@ class Doctrine:
data["ground_unit_procurement_ratios"] data["ground_unit_procurement_ratios"]
), ),
helicopter=Helicopter.from_dict(data["helicopter"]), helicopter=Helicopter.from_dict(data["helicopter"]),
aewc=Aewc.from_dict(data["aewc"]),
cas=Cas.from_dict(data["cas"]), cas=Cas.from_dict(data["cas"]),
cap=Cap.from_dict(data["cap"]), cap=Cap.from_dict(data["cap"]),
sweep=Sweep.from_dict(data["sweep"]), sweep=Sweep.from_dict(data["sweep"]),

View File

@@ -38,7 +38,6 @@ from game.radio.channels import (
HindChannelNamer, HindChannelNamer,
HipChannelNamer, HipChannelNamer,
KiowaChannelNamer, KiowaChannelNamer,
FulcrumChannelNamer,
) )
from game.utils import ( from game.utils import (
Distance, Distance,
@@ -119,7 +118,6 @@ class RadioConfig:
"hind": HindChannelNamer, "hind": HindChannelNamer,
"hip": HipChannelNamer, "hip": HipChannelNamer,
"kiowa": KiowaChannelNamer, "kiowa": KiowaChannelNamer,
"fulcrum": FulcrumChannelNamer,
}[config.get("namer", "default")] }[config.get("namer", "default")]

View File

@@ -196,9 +196,6 @@ class StateData:
#: True if the mission ended. If False, the mission exited abnormally. #: True if the mission ended. If False, the mission exited abnormally.
mission_ended: bool mission_ended: bool
#: Simulation time since mission start in seconds
simulation_time_seconds: float
#: Names of aircraft units that were killed during the mission. #: Names of aircraft units that were killed during the mission.
killed_aircraft: List[str] killed_aircraft: List[str]
@@ -251,7 +248,6 @@ class StateData:
return cls( return cls(
mission_ended=data["mission_ended"], mission_ended=data["mission_ended"],
simulation_time_seconds=data["simulation_time_seconds"],
killed_aircraft=killed_aircraft, killed_aircraft=killed_aircraft,
killed_ground_units=killed_ground_units, killed_ground_units=killed_ground_units,
destroyed_statics=data["destroyed_objects_positions"], destroyed_statics=data["destroyed_objects_positions"],

View File

@@ -125,11 +125,7 @@ class Game:
self.time_of_day_offset_for_start_time = list(TimeOfDay).index( self.time_of_day_offset_for_start_time = list(TimeOfDay).index(
self.theater.daytime_map.best_guess_time_of_day_at(start_time) self.theater.daytime_map.best_guess_time_of_day_at(start_time)
) )
# self.conditions.start_time is the time at the start of a turn and does not change within a turn.
# self.simulation_time tracks time progression within a turn and is synchronized with the
# MissionSimulation object.
self.conditions = self.generate_conditions(forced_time=start_time) self.conditions = self.generate_conditions(forced_time=start_time)
self.simulation_time = self.conditions.start_time
self.sanitize_sides(player_faction, enemy_faction) self.sanitize_sides(player_faction, enemy_faction)
self.blue = Coalition(self, player_faction, player_budget, player=True) self.blue = Coalition(self, player_faction, player_budget, player=True)
@@ -295,7 +291,6 @@ class Game:
# turn 1. # turn 1.
if self.turn > 1: if self.turn > 1:
self.conditions = self.generate_conditions() self.conditions = self.generate_conditions()
self.simulation_time = self.conditions.start_time
def begin_turn_0(self) -> None: def begin_turn_0(self) -> None:
"""Initialization for the first turn of the game.""" """Initialization for the first turn of the game."""

View File

@@ -148,7 +148,7 @@ class AircraftGenerator:
faction.country, faction.country,
squadron, squadron,
1, 1,
FlightType.IDLE, FlightType.BARCAP,
StartType.COLD, StartType.COLD,
divert=None, divert=None,
) )

View File

@@ -285,7 +285,7 @@ class FlightGroupConfigurator:
if ( if (
unit_callsign.name is None unit_callsign.name is None
): # pydcs needs unit.callsign to be set for eastern callsigns ): # pydcs needs unit.callsign to be set for eastern callsigns
unit.callsign = str(unit_callsign) unit.callsign = str(unit_callsign) # type: ignore
else: # Use western callsign else: # Use western callsign
unit.callsign_dict = unit_callsign.pydcs_dict( unit.callsign_dict = unit_callsign.pydcs_dict(
country=self.flight.country country=self.flight.country

View File

@@ -243,7 +243,11 @@ class FlightGroupSpawner:
for i in range(self.flight.count): for i in range(self.flight.count):
group.units[i].position = hpad.position group.units[i].position = hpad.position
group.units[i].heading = hpad.heading group.units[i].heading = hpad.heading
group.units[i].parking_id = str(i + 1) # pydcs has just `parking_id = None`, so mypy thinks str is invalid. Ought
# to fix pydcs, but that's not the kind of change we want to pull into the
# 6.1 branch, and frankly we should probably just improve pydcs's handling
# of FARPs instead.
group.units[i].parking_id = str(i + 1) # type: ignore
return group return group
def dcs_start_type(self) -> DcsStartType: def dcs_start_type(self) -> DcsStartType:

View File

@@ -4,7 +4,7 @@ from datetime import datetime
from typing import Any, Iterable, Union from typing import Any, Iterable, Union
from dcs import Mission from dcs import Mission
from dcs.planes import AJS37, F_14A_135_GR, F_14A_135_GR_Early, F_14B, JF_17 from dcs.planes import AJS37, F_14B, JF_17
from dcs.point import MovingPoint, PointAction from dcs.point import MovingPoint, PointAction
from dcs.unitgroup import FlyingGroup from dcs.unitgroup import FlyingGroup
@@ -127,9 +127,5 @@ class PydcsWaypointBuilder:
for i, t in enumerate(targets): for i, t in enumerate(targets):
if self.group.units[0].unit_type == JF_17 and i < 4: if self.group.units[0].unit_type == JF_17 and i < 4:
self.group.add_nav_target_point(t.position, "PP" + str(i + 1)) self.group.add_nav_target_point(t.position, "PP" + str(i + 1))
if ( if self.group.units[0].unit_type == F_14B and i == 0:
self.group.units[0].unit_type
in [F_14A_135_GR, F_14A_135_GR_Early, F_14B]
and i == 0
):
self.group.add_nav_target_point(t.position, "ST") self.group.add_nav_target_point(t.position, "ST")

View File

@@ -450,15 +450,3 @@ class KiowaChannelNamer(ChannelNamer):
@classmethod @classmethod
def name(cls) -> str: def name(cls) -> str:
return "kiowa" return "kiowa"
class FulcrumChannelNamer(ChannelNamer):
"""Channel namer for MiG-29A Fulcrum"""
@staticmethod
def channel_name(radio_id: int, channel_id: int) -> str:
return f"R862 Ch {channel_id}"
@classmethod
def name(cls) -> str:
return "fulcrum"

View File

@@ -234,6 +234,7 @@ RADIOS: List[Radio] = [
# Ka-50 # Ka-50
# Note: Also capable of 100MHz-150MHz, but we can't model gaps. # Note: Also capable of 100MHz-150MHz, but we can't model gaps.
Radio("R-800L1", (RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM),)), Radio("R-800L1", (RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM),)),
Radio("R-828", (RadioRange(MHz(20), MHz(60), kHz(25), Modulation.FM),)),
# UH-1H # UH-1H
Radio("AN/ARC-51BX", (RadioRange(MHz(225), MHz(400), kHz(50), Modulation.AM),)), Radio("AN/ARC-51BX", (RadioRange(MHz(225), MHz(400), kHz(50), Modulation.AM),)),
Radio("AN/ARC-131", (RadioRange(MHz(30), MHz(76), kHz(50), Modulation.FM),)), Radio("AN/ARC-131", (RadioRange(MHz(30), MHz(76), kHz(50), Modulation.FM),)),
@@ -297,16 +298,6 @@ RADIOS: List[Radio] = [
# Mi-8/Mi-24 # Mi-8/Mi-24
Radio("R863", (RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM),)), Radio("R863", (RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM),)),
Radio("R828", (RadioRange(MHz(20), MHz(60), kHz(25), Modulation.FM),)), Radio("R828", (RadioRange(MHz(20), MHz(60), kHz(25), Modulation.FM),)),
# MiG-29A
Radio(
"R862",
(
RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM),
RadioRange(MHz(100), MHz(150), kHz(25), Modulation.AM),
RadioRange(MHz(220), MHz(400), kHz(25), Modulation.FM),
RadioRange(MHz(100), MHz(150), kHz(25), Modulation.FM),
),
),
] ]

View File

@@ -35,7 +35,6 @@ class FastForwardStopCondition(Enum):
PLAYER_TAKEOFF = "Player takeoff time" PLAYER_TAKEOFF = "Player takeoff time"
PLAYER_TAXI = "Player taxi time" PLAYER_TAXI = "Player taxi time"
PLAYER_STARTUP = "Player startup time" PLAYER_STARTUP = "Player startup time"
PLAYER_AT_IP = "Player at IP"
MANUAL = "Manual fast forward control" MANUAL = "Manual fast forward control"
@@ -356,16 +355,6 @@ class Settings:
"your game after aborting take off." "your game after aborting take off."
), ),
) )
turnless_mode: bool = boolean_option(
"Enable turnless mode (WIP)",
page=MISSION_GENERATOR_PAGE,
section=GAMEPLAY_SECTION,
default=False,
detail=(
"If enabled, turns do not end after mission completion. A new mission "
"can be started picking up from where the previous mission ended."
),
)
fast_forward_stop_condition: FastForwardStopCondition = choices_option( fast_forward_stop_condition: FastForwardStopCondition = choices_option(
"Fast forward until", "Fast forward until",
page=MISSION_GENERATOR_PAGE, page=MISSION_GENERATOR_PAGE,
@@ -376,7 +365,6 @@ class Settings:
"Player startup time": FastForwardStopCondition.PLAYER_STARTUP, "Player startup time": FastForwardStopCondition.PLAYER_STARTUP,
"Player taxi time": FastForwardStopCondition.PLAYER_TAXI, "Player taxi time": FastForwardStopCondition.PLAYER_TAXI,
"Player takeoff time": FastForwardStopCondition.PLAYER_TAKEOFF, "Player takeoff time": FastForwardStopCondition.PLAYER_TAKEOFF,
"Player at IP": FastForwardStopCondition.PLAYER_AT_IP,
"First contact": FastForwardStopCondition.FIRST_CONTACT, "First contact": FastForwardStopCondition.FIRST_CONTACT,
"Manual": FastForwardStopCondition.MANUAL, "Manual": FastForwardStopCondition.MANUAL,
}, },

View File

@@ -7,7 +7,9 @@ from datetime import datetime, timedelta
from typing_extensions import TYPE_CHECKING from typing_extensions import TYPE_CHECKING
from game.ato.flightstate import Uninitialized, Completed, InCombat from game.ato.flightstate import (
Uninitialized,
)
from game.settings.settings import FastForwardStopCondition, CombatResolutionMethod from game.settings.settings import FastForwardStopCondition, CombatResolutionMethod
from .combat import CombatInitiator, FrozenCombat from .combat import CombatInitiator, FrozenCombat
from .gameupdateevents import GameUpdateEvents from .gameupdateevents import GameUpdateEvents
@@ -25,20 +27,13 @@ class AircraftSimulation:
self.results = SimulationResults() self.results = SimulationResults()
def begin_simulation(self) -> None: def begin_simulation(self) -> None:
self.reset()
self.set_initial_flight_states() self.set_initial_flight_states()
def on_game_tick( def on_game_tick(
self, self, events: GameUpdateEvents, time: datetime, duration: timedelta
events: GameUpdateEvents,
time: datetime,
duration: timedelta,
combat_resolution_method: CombatResolutionMethod,
force_continue: bool,
) -> None: ) -> None:
if ( if not self._auto_resolve_combat() and self.combats:
not self._auto_resolve_combat(combat_resolution_method, force_continue)
and self.combats
):
logging.error( logging.error(
"Cannot resume simulation because aircraft are in combat and " "Cannot resume simulation because aircraft are in combat and "
"auto-resolve is disabled" "auto-resolve is disabled"
@@ -53,7 +48,7 @@ class AircraftSimulation:
duration, duration,
self.results, self.results,
events, events,
combat_resolution_method, self.game.settings.combat_resolution_method,
): ):
events.end_combat(combat) events.end_combat(combat)
else: else:
@@ -69,38 +64,22 @@ class AircraftSimulation:
# After updating all combat states, check for halts. # After updating all combat states, check for halts.
for flight in self.iter_flights(): for flight in self.iter_flights():
if flight.should_halt_sim() and not force_continue: if flight.should_halt_sim():
events.complete_simulation() events.complete_simulation()
return return
# Find completed flights, removing them from the ATO and returning aircraft if not self._auto_resolve_combat() and self.combats:
# and pilots back to the squadron.
for flight in self.iter_flights():
if type(flight.state) == Completed:
flight.package.remove_flight(flight)
if len(flight.package.flights) == 0:
flight.squadron.coalition.ato.remove_package(flight.package)
if (
not self._auto_resolve_combat(combat_resolution_method, force_continue)
and self.combats
):
events.complete_simulation() events.complete_simulation()
def set_initial_flight_states(self) -> None: def set_initial_flight_states(self) -> None:
# Initialize flights in Uninitialized state now = self.game.conditions.start_time
now = self.game.simulation_time
for flight in self.iter_flights(): for flight in self.iter_flights():
flight.state.initialize(now) flight.state.reinitialize(now)
# Recover combat instances from flight states. Flight state information is serialized def reset(self) -> None:
# when saving a game but the aircraft simulation state is not. Combat instances are
# de-duplicated as multiple flights can be involved in a single combat instance.
combats = set()
for flight in self.iter_flights(): for flight in self.iter_flights():
if type(flight.state) == InCombat: flight.set_state(Uninitialized(flight, self.game.settings))
combats.add(flight.state.combat) self.combats = []
self.combats = list(combats)
def iter_flights(self) -> Iterator[Flight]: def iter_flights(self) -> Iterator[Flight]:
packages = itertools.chain( packages = itertools.chain(
@@ -109,9 +88,10 @@ class AircraftSimulation:
for package in packages: for package in packages:
yield from package.flights yield from package.flights
def _auto_resolve_combat( def _auto_resolve_combat(self) -> bool:
self, combat_resolution_method: CombatResolutionMethod, force_continue: bool return (
) -> bool: self.game.settings.fast_forward_stop_condition
if force_continue: != FastForwardStopCondition.DISABLED
return True and self.game.settings.combat_resolution_method
return combat_resolution_method != CombatResolutionMethod.PAUSE != CombatResolutionMethod.PAUSE
)

View File

@@ -100,11 +100,7 @@ class GameLoop:
if not self.started: if not self.started:
raise RuntimeError("Attempted to tick game loop before initialization") raise RuntimeError("Attempted to tick game loop before initialization")
try: try:
self.sim.tick( self.sim.tick(self.events)
self.events,
self.game.settings.combat_resolution_method,
force_continue=False,
)
self.completed = self.events.simulation_complete self.completed = self.events.simulation_complete
if not suppress_events: if not suppress_events:
self.send_update(rate_limit=True) self.send_update(rate_limit=True)

View File

@@ -8,7 +8,6 @@ from game.ground_forces.combat_stance import CombatStance
from game.theater import ControlPoint from game.theater import ControlPoint
from .gameupdateevents import GameUpdateEvents from .gameupdateevents import GameUpdateEvents
from ..ato.airtaaskingorder import AirTaskingOrder from ..ato.airtaaskingorder import AirTaskingOrder
from ..ato.flightstate.atdeparture import AtDeparture
if TYPE_CHECKING: if TYPE_CHECKING:
from ..game import Game from ..game import Game
@@ -58,25 +57,6 @@ class MissionResultsProcessor:
logging.info(f"{aircraft} destroyed from {squadron}") logging.info(f"{aircraft} destroyed from {squadron}")
squadron.owned_aircraft -= 1 squadron.owned_aircraft -= 1
# Remove air losses from the flight. Remove the flight if all aircraft are lost.
# Remove the package if the flight is the last flight in the package.
# This logic is redundant if we are going to a new turn, since the whole ATO is
# regenerated. However if we want to keep the ATO to continue a turn, this update
# is necessary to make sure lost aircraft are removed from the ATO.
if loss.pilot is not None:
loss.flight.roster.remove_pilot(loss.pilot)
if loss.flight.count == 0: # Last aircraft in the flight, remove the flight
# If no flights in package, generally indicates that the loss is an aircraft
# that is not assigned to a mission and is parked on the ground. There is no need
# to remove the aircraft from the ATO as it was never in the ATO in the first place.
if len(loss.flight.package.flights) == 0:
continue
loss.flight.package.remove_flight(loss.flight)
if len(loss.flight.package.flights) == 0:
loss.flight.squadron.coalition.ato.remove_package(
loss.flight.package
)
@staticmethod @staticmethod
def _commit_pilot_experience(ato: AirTaskingOrder) -> None: def _commit_pilot_experience(ato: AirTaskingOrder) -> None:
for package in ato.packages: for package in ato.packages:
@@ -168,21 +148,10 @@ class MissionResultsProcessor:
iads_network.update_network(events) iads_network.update_network(events)
return return
def commit_damaged_runways(self, debriefing: Debriefing) -> None: @staticmethod
def commit_damaged_runways(debriefing: Debriefing) -> None:
for damaged_runway in debriefing.damaged_runways: for damaged_runway in debriefing.damaged_runways:
damaged_runway.damage_runway() damaged_runway.damage_runway()
# Remove any flight in ATO scheduled to take off from the damaged runway.
for coalition in self.game.coalitions:
for package in coalition.ato.packages:
for flight in package.flights:
if flight.departure.name == damaged_runway.name and isinstance(
flight.state, AtDeparture
):
flight.package.remove_flight(flight)
if len(flight.package.flights) == 0:
flight.squadron.coalition.ato.remove_package(
flight.package
)
def commit_captures(self, debriefing: Debriefing, events: GameUpdateEvents) -> None: def commit_captures(self, debriefing: Debriefing, events: GameUpdateEvents) -> None:
for captured in debriefing.base_captures: for captured in debriefing.base_captures:

View File

@@ -1,5 +1,5 @@
from __future__ import annotations from __future__ import annotations
import copy
import json import json
from datetime import timedelta from datetime import timedelta
from pathlib import Path from pathlib import Path
@@ -7,7 +7,6 @@ from typing import Optional, TYPE_CHECKING
from game.debriefing import Debriefing from game.debriefing import Debriefing
from game.missiongenerator import MissionGenerator from game.missiongenerator import MissionGenerator
from game.settings.settings import FastForwardStopCondition, CombatResolutionMethod
from game.unitmap import UnitMap from game.unitmap import UnitMap
from .aircraftsimulation import AircraftSimulation from .aircraftsimulation import AircraftSimulation
from .missionresultsprocessor import MissionResultsProcessor from .missionresultsprocessor import MissionResultsProcessor
@@ -32,31 +31,17 @@ class MissionSimulation:
self.unit_map: Optional[UnitMap] = None self.unit_map: Optional[UnitMap] = None
self.aircraft_simulation = AircraftSimulation(self.game) self.aircraft_simulation = AircraftSimulation(self.game)
self.completed = False self.completed = False
self.time = self.game.simulation_time self.time = self.game.conditions.start_time
def begin_simulation(self) -> None: def begin_simulation(self) -> None:
self.time = self.game.simulation_time self.time = self.game.conditions.start_time
self.aircraft_simulation.begin_simulation() self.aircraft_simulation.begin_simulation()
def tick( def tick(self, events: GameUpdateEvents) -> GameUpdateEvents:
self,
events: GameUpdateEvents,
combat_resolution_method: CombatResolutionMethod,
force_continue: bool,
) -> GameUpdateEvents:
self.time += TICK self.time += TICK
self.game.simulation_time = self.time
if self.completed: if self.completed:
raise RuntimeError("Simulation already completed") raise RuntimeError("Simulation already completed")
if ( self.aircraft_simulation.on_game_tick(events, self.time, TICK)
self.game.settings.fast_forward_stop_condition
== FastForwardStopCondition.DISABLED
):
events.complete_simulation()
return events
self.aircraft_simulation.on_game_tick(
events, self.time, TICK, combat_resolution_method, force_continue
)
self.completed = events.simulation_complete self.completed = events.simulation_complete
return events return events
@@ -90,24 +75,6 @@ class MissionSimulation:
self.game.save_last_turn_state() self.game.save_last_turn_state()
MissionResultsProcessor(self.game).commit(debriefing, events) MissionResultsProcessor(self.game).commit(debriefing, events)
if self.game.settings.turnless_mode:
# Set completed to False to clear completion of any previous simulation tick.
self.completed = False
# If running in turnless mode, run sim to calculate planned positions of flights
# for the duration of time the DCS mission ran.
start_time = copy.deepcopy(self.time)
while self.time < start_time + timedelta(
seconds=int(debriefing.state_data.simulation_time_seconds)
):
# Always skip combat as we are processing results from DCS. Any combat has already
# been resolved in-game
self.tick(events, CombatResolutionMethod.SKIP, force_continue=True)
self.game.blue.plan_missions(self.game.simulation_time)
self.game.red.plan_missions(self.game.simulation_time)
self.game.game_stats.update(self.game)
# Generate begin_new_turn event which triggers a refresh of the React map screen to
# show newly planned missions.
events.begin_new_turn()
def finish(self) -> None: def finish(self) -> None:
self.unit_map = None self.unit_map = None

File diff suppressed because it is too large Load Diff

View File

@@ -9,11 +9,17 @@ from pydcs_extensions.weapon_injector import inject_weapons
class Su57Weapons: class Su57Weapons:
Kh_59MK2 = {"clsid": "{KH_59MK2}", "name": "Kh-59MK2", "weight": None}
RVV_AE = {"clsid": "{RVV-AE}", "name": "RVV-AE", "weight": 250} RVV_AE = {"clsid": "{RVV-AE}", "name": "RVV-AE", "weight": 250}
RVV_BD = {"clsid": "{RVV-BD}", "name": "RVV-BD", "weight": 600} RVV_BD = {"clsid": "{RVV-BD}", "name": "RVV-BD", "weight": 600}
RVV_L = {"clsid": "{RVV-L}", "name": "RVV-L", "weight": 748} RVV_L = {"clsid": "{RVV-L}", "name": "RVV-L", "weight": 748}
RVV_M = {"clsid": "{RVV-M}", "name": "RVV-M", "weight": 190} RVV_M = {"clsid": "{RVV-M}", "name": "RVV-M", "weight": 190}
R_37M_Active_Rdr = {"clsid": "{RVV-BD}", "name": "R-37M Active Rdr", "weight": 600} R_37M_Active_Rdr = {"clsid": "{RVV-BD}", "name": "R-37M Active Rdr", "weight": 600}
Su_57_Fuel_Tank = {
"clsid": "{SU_57Tank}",
"name": "Su-57 Fuel Tank",
"weight": 1561.421,
}
R_77PD_Active_rdr = { R_77PD_Active_rdr = {
"clsid": "{RVV-AE}", "clsid": "{RVV-AE}",
"name": "R-77PD Active rdr", "name": "R-77PD Active rdr",
@@ -50,10 +56,8 @@ class Su_57(PlaneType):
class Pylon1: class Pylon1:
R_73__AA_11_Archer____Infra_Red = (1, Weapons.R_73__AA_11_Archer____Infra_Red) R_73__AA_11_Archer____Infra_Red = (1, Weapons.R_73__AA_11_Archer____Infra_Red)
KS_172_Passive_Rdr = (1, Weapons.KS_172_Passive_Rdr) R_77PD_Active_rdr = (1, Su57Weapons.R_77PD_Active_rdr)
# ERRR {RVV-AE} K_77M_Active_Rdr = (1, Su57Weapons.K_77M_Active_Rdr)
R_77PD_Active_rdr = (1, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (1, Weapons.K_77M_Active_Rdr)
L_081_Fantasmagoria_ELINT_pod = (1, Weapons.L_081_Fantasmagoria_ELINT_pod) L_081_Fantasmagoria_ELINT_pod = (1, Weapons.L_081_Fantasmagoria_ELINT_pod)
Smoke_Generator___red = (1, Weapons.Smoke_Generator___red) Smoke_Generator___red = (1, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (1, Weapons.Smoke_Generator___green) Smoke_Generator___green = (1, Weapons.Smoke_Generator___green)
@@ -89,37 +93,37 @@ class Su_57(PlaneType):
2, 2,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr, Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
) )
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_ = ( Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser = (
2, 2,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_, Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser,
) )
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_ = ( Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided = (
2, 2,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_, Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided,
) )
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = ( Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
2, 2,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN, Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
) )
MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD = ( MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD = (
2, 2,
Weapons.MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD, Weapons.MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD,
) )
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = ( B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
2, 2,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag, Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
) )
B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation = ( B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
2, 2,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation, Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
) )
O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator = ( S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
2, 2,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator, Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
) )
BetAB_500___500_kg_Concrete_Piercing_Bomb_LD = ( BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
2, 2,
Weapons.BetAB_500___500_kg_Concrete_Piercing_Bomb_LD, Weapons.BetAB_500___500kg_Concrete_Piercing_Bomb_LD,
) )
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = ( KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
2, 2,
@@ -129,12 +133,12 @@ class Su_57(PlaneType):
2, 2,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP, Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
) )
OFAB_250_270___250_kg_GP_Bomb_LD = (2, Weapons.OFAB_250_270___250_kg_GP_Bomb_LD) FAB_250___250kg_GP_Bomb_LD = (2, Weapons.FAB_250___250kg_GP_Bomb_LD)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = ( RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
2, 2,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP, Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
) )
FAB_500M_62___500_kg_GP_Bomb_LD = (2, Weapons.FAB_500M_62___500_kg_GP_Bomb_LD) FAB_500_M_62___500kg_GP_Bomb_LD = (2, Weapons.FAB_500_M_62___500kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = ( RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
2, 2,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP, Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
@@ -152,20 +156,21 @@ class Su_57(PlaneType):
2, 2,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb, Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
) )
MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD = ( MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD = (
2, 2,
Weapons.MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD, Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
) )
R_37M_Active_Rdr = (2, Weapons.R_37M_Active_Rdr) R_37M_Active_Rdr = (2, Su57Weapons.R_37M_Active_Rdr)
# ERRR {RVV-AE} R_77PD_Active_rdr = (2, Su57Weapons.R_77PD_Active_rdr)
R_77PD_Active_rdr = (2, Weapons.R_77PD_Active_rdr) K_77M_Active_Rdr = (2, Su57Weapons.K_77M_Active_Rdr)
K_77M_Active_Rdr = (2, Weapons.K_77M_Active_Rdr) KS_172_Passive_Rdr = (2, Su57Weapons.KS_172_Passive_Rdr)
KS_172_Passive_Rdr = (2, Weapons.KS_172_Passive_Rdr)
Fuel_tank_800L_Wing = (2, Weapons.Fuel_tank_800L_Wing) Fuel_tank_800L_Wing = (2, Weapons.Fuel_tank_800L_Wing)
RN_28___260_kg__nuclear_bomb__free_fall = ( RN_28___260_kg__nuclear_bomb__free_fall = (
2, 2,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall, Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
) )
Su_57_Fuel_Tank = (2, Su57Weapons.Su_57_Fuel_Tank)
Kh_59MK2 = (2, Su57Weapons.Kh_59MK2)
Smoke_Generator___red = (2, Weapons.Smoke_Generator___red) Smoke_Generator___red = (2, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (2, Weapons.Smoke_Generator___green) Smoke_Generator___green = (2, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (2, Weapons.Smoke_Generator___blue) Smoke_Generator___blue = (2, Weapons.Smoke_Generator___blue)
@@ -209,37 +214,37 @@ class Su_57(PlaneType):
4, 4,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr, Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
) )
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_ = ( Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser = (
4, 4,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_, Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser,
) )
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_ = ( Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided = (
4, 4,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_, Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided,
) )
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = ( Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
4, 4,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN, Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
) )
MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD = ( MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD = (
4, 4,
Weapons.MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD, Weapons.MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD,
) )
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = ( B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
4, 4,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag, Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
) )
B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation = ( B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
4, 4,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation, Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
) )
O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator = ( S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
4, 4,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator, Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
) )
BetAB_500___500_kg_Concrete_Piercing_Bomb_LD = ( BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
4, 4,
Weapons.BetAB_500___500_kg_Concrete_Piercing_Bomb_LD, Weapons.BetAB_500___500kg_Concrete_Piercing_Bomb_LD,
) )
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = ( KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
4, 4,
@@ -249,12 +254,12 @@ class Su_57(PlaneType):
4, 4,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP, Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
) )
OFAB_250_270___250_kg_GP_Bomb_LD = (4, Weapons.OFAB_250_270___250_kg_GP_Bomb_LD) FAB_250___250kg_GP_Bomb_LD = (4, Weapons.FAB_250___250kg_GP_Bomb_LD)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = ( RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
4, 4,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP, Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
) )
FAB_500M_62___500_kg_GP_Bomb_LD = (4, Weapons.FAB_500M_62___500_kg_GP_Bomb_LD) FAB_500_M_62___500kg_GP_Bomb_LD = (4, Weapons.FAB_500_M_62___500kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = ( RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
4, 4,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP, Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
@@ -272,61 +277,158 @@ class Su_57(PlaneType):
4, 4,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb, Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
) )
MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD = ( MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD = (
4, 4,
Weapons.MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD, Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
) )
R_37M_Active_Rdr = (4, Weapons.R_37M_Active_Rdr) R_37M_Active_Rdr = (4, Su57Weapons.R_37M_Active_Rdr)
# ERRR {RVV-AE} R_77PD_Active_rdr = (4, Su57Weapons.R_77PD_Active_rdr)
R_77PD_Active_rdr = (4, Weapons.R_77PD_Active_rdr) K_77M_Active_Rdr = (4, Su57Weapons.K_77M_Active_Rdr)
K_77M_Active_Rdr = (4, Weapons.K_77M_Active_Rdr) KS_172_Passive_Rdr = (4, Su57Weapons.KS_172_Passive_Rdr)
KS_172_Passive_Rdr = (4, Weapons.KS_172_Passive_Rdr)
RN_28___260_kg__nuclear_bomb__free_fall = ( RN_28___260_kg__nuclear_bomb__free_fall = (
4, 4,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall, Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
) )
Su_57_Fuel_Tank = (4, Su57Weapons.Su_57_Fuel_Tank)
Kh_59MK2 = (4, Su57Weapons.Kh_59MK2)
class Pylon5: class Pylon5:
R_77__AA_12_Adder____Active_Rdr = (5, Weapons.R_77__AA_12_Adder____Active_Rdr) R_77__AA_12_Adder____Active_Rdr = (5, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE} R_77PD_Active_rdr = (5, Su57Weapons.R_77PD_Active_rdr)
R_77PD_Active_rdr = (5, Weapons.R_77PD_Active_rdr) K_77M_Active_Rdr = (5, Su57Weapons.K_77M_Active_Rdr)
K_77M_Active_Rdr = (5, Weapons.K_77M_Active_Rdr) Kh_59MK2 = (5, Su57Weapons.Kh_59MK2)
KS_172_Passive_Rdr = (5, Weapons.KS_172_Passive_Rdr)
class Pylon6: class Pylon6:
R_77__AA_12_Adder____Active_Rdr = (6, Weapons.R_77__AA_12_Adder____Active_Rdr) R_77__AA_12_Adder____Active_Rdr = (6, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE} R_77PD_Active_rdr = (6, Su57Weapons.R_77PD_Active_rdr)
R_77PD_Active_rdr = (6, Weapons.R_77PD_Active_rdr) K_77M_Active_Rdr = (6, Su57Weapons.K_77M_Active_Rdr)
K_77M_Active_Rdr = (6, Weapons.K_77M_Active_Rdr) Kh_59MK2 = (6, Su57Weapons.Kh_59MK2)
KS_172_Passive_Rdr = (6, Weapons.KS_172_Passive_Rdr)
class Pylon7: class Pylon7:
R_77__AA_12_Adder____Active_Rdr = (7, Weapons.R_77__AA_12_Adder____Active_Rdr) R_77__AA_12_Adder____Active_Rdr = (7, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE} R_77PD_Active_rdr = (7, Su57Weapons.R_77PD_Active_rdr)
R_77PD_Active_rdr = (7, Weapons.R_77PD_Active_rdr) K_77M_Active_Rdr = (7, Su57Weapons.K_77M_Active_Rdr)
K_77M_Active_Rdr = (7, Weapons.K_77M_Active_Rdr) Kh_59MK2 = (7, Su57Weapons.Kh_59MK2)
KS_172_Passive_Rdr = (7, Weapons.KS_172_Passive_Rdr)
class Pylon8: class Pylon8:
R_77__AA_12_Adder____Active_Rdr = (8, Weapons.R_77__AA_12_Adder____Active_Rdr) R_77__AA_12_Adder____Active_Rdr = (8, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE} R_77PD_Active_rdr = (8, Su57Weapons.R_77PD_Active_rdr)
R_77PD_Active_rdr = (8, Weapons.R_77PD_Active_rdr) K_77M_Active_Rdr = (8, Su57Weapons.K_77M_Active_Rdr)
K_77M_Active_Rdr = (8, Weapons.K_77M_Active_Rdr) Kh_59MK2 = (8, Su57Weapons.Kh_59MK2)
KS_172_Passive_Rdr = (8, Weapons.KS_172_Passive_Rdr)
class Pylon9: class Pylon9:
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
9,
Weapons.R_27R__AA_10_Alamo_A____Semi_Act_Rdr,
)
R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range = (
9,
Weapons.R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range,
)
R_27T__AA_10_Alamo_B____Infra_Red = (
9,
Weapons.R_27T__AA_10_Alamo_B____Infra_Red,
)
R_27ET__AA_10_Alamo_D____IR_Extended_Range = (
9,
Weapons.R_27ET__AA_10_Alamo_D____IR_Extended_Range,
)
R_77__AA_12_Adder____Active_Rdr = (9, Weapons.R_77__AA_12_Adder____Active_Rdr) R_77__AA_12_Adder____Active_Rdr = (9, Weapons.R_77__AA_12_Adder____Active_Rdr)
# ERRR {RVV-AE} R_73__AA_11_Archer____Infra_Red = (9, Weapons.R_73__AA_11_Archer____Infra_Red)
R_77PD_Active_rdr = (9, Weapons.R_77PD_Active_rdr) Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr = (
K_77M_Active_Rdr = (9, Weapons.K_77M_Active_Rdr) 9,
KS_172_Passive_Rdr = (9, Weapons.KS_172_Passive_Rdr) Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr,
)
Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr = (
9,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
)
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser = (
9,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser,
)
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided = (
9,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided,
)
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
9,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
)
MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD = (
9,
Weapons.MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD,
)
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
9,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
)
B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
9,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
)
S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
9,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
)
BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
9,
Weapons.BetAB_500___500kg_Concrete_Piercing_Bomb_LD,
)
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
9,
Weapons.KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag,
)
KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP = (
9,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
)
FAB_250___250kg_GP_Bomb_LD = (9, Weapons.FAB_250___250kg_GP_Bomb_LD)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
9,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
)
FAB_500_M_62___500kg_GP_Bomb_LD = (9, Weapons.FAB_500_M_62___500kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
9,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
)
KAB_500LG___500kg_Laser_Guided_Bomb = (
9,
Weapons.KAB_500LG___500kg_Laser_Guided_Bomb,
)
KAB_500Kr___500kg_TV_Guided_Bomb = (9, Weapons.KAB_500Kr___500kg_TV_Guided_Bomb)
FAB_1500_M_54___1500kg_GP_Bomb_LD = (
9,
Weapons.FAB_1500_M_54___1500kg_GP_Bomb_LD,
)
KAB_1500L___1500kg_Laser_Guided_Bomb = (
9,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
)
MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD = (
9,
Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
)
R_37M_Active_Rdr = (9, Su57Weapons.R_37M_Active_Rdr)
R_77PD_Active_rdr = (9, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (9, Su57Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (9, Su57Weapons.KS_172_Passive_Rdr)
RN_28___260_kg__nuclear_bomb__free_fall = (
9,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
)
Su_57_Fuel_Tank = (9, Su57Weapons.Su_57_Fuel_Tank)
Kh_59MK2 = (9, Su57Weapons.Kh_59MK2)
class Pylon10: class Pylon10:
R_77__AA_12_Adder____Active_Rdr = (10, Weapons.R_77__AA_12_Adder____Active_Rdr) R_73__AA_11_Archer____Infra_Red = (10, Weapons.R_73__AA_11_Archer____Infra_Red)
# ERRR {RVV-AE} Smoke_Generator___red = (10, Weapons.Smoke_Generator___red)
R_77PD_Active_rdr = (10, Weapons.R_77PD_Active_rdr) Smoke_Generator___green = (10, Weapons.Smoke_Generator___green)
K_77M_Active_Rdr = (10, Weapons.K_77M_Active_Rdr) Smoke_Generator___blue = (10, Weapons.Smoke_Generator___blue)
KS_172_Passive_Rdr = (10, Weapons.KS_172_Passive_Rdr) Smoke_Generator___white = (10, Weapons.Smoke_Generator___white)
Smoke_Generator___yellow = (10, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (10, Weapons.Smoke_Generator___orange)
class Pylon11: class Pylon11:
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = ( R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
@@ -355,37 +457,37 @@ class Su_57(PlaneType):
11, 11,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr, Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
) )
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_ = ( Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser = (
11, 11,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_, Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser,
) )
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_ = ( Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided = (
11, 11,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_, Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided,
) )
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = ( Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
11, 11,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN, Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
) )
MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD = ( MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD = (
11, 11,
Weapons.MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD, Weapons.MBD3_U6_68_with_6_x_FAB_100___100kg_GP_Bombs_LD,
) )
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = ( B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
11, 11,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag, Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
) )
B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation = ( B_13L_pod___5_x_S_13_OF__122mm_UnGd_Rkts__Blast_Frag = (
11, 11,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation, Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
) )
O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator = ( S_25_OFM___340mm_UnGd_Rkt__480kg_Penetrator = (
11, 11,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator, Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
) )
BetAB_500___500_kg_Concrete_Piercing_Bomb_LD = ( BetAB_500___500kg_Concrete_Piercing_Bomb_LD = (
11, 11,
Weapons.BetAB_500___500_kg_Concrete_Piercing_Bomb_LD, Weapons.BetAB_500___500kg_Concrete_Piercing_Bomb_LD,
) )
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = ( KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
11, 11,
@@ -395,15 +497,12 @@ class Su_57(PlaneType):
11, 11,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP, Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
) )
OFAB_250_270___250_kg_GP_Bomb_LD = ( FAB_250___250kg_GP_Bomb_LD = (11, Weapons.FAB_250___250kg_GP_Bomb_LD)
11,
Weapons.OFAB_250_270___250_kg_GP_Bomb_LD,
)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = ( RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
11, 11,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP, Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
) )
FAB_500M_62___500_kg_GP_Bomb_LD = (11, Weapons.FAB_500M_62___500_kg_GP_Bomb_LD) FAB_500_M_62___500kg_GP_Bomb_LD = (11, Weapons.FAB_500_M_62___500kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = ( RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
11, 11,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP, Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
@@ -424,22 +523,33 @@ class Su_57(PlaneType):
11, 11,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb, Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
) )
MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD = ( MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD = (
11, 11,
Weapons.MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD, Weapons.MBD3_U6_68_with_6_x_FAB_250___250kg_GP_Bombs_LD,
) )
R_37M_Active_Rdr = (11, Weapons.R_37M_Active_Rdr) # ERRR {R-33}
# ERRR {RVV-AE} R_37M_Active_Rdr = (11, Su57Weapons.R_37M_Active_Rdr)
R_77PD_Active_rdr = (11, Weapons.R_77PD_Active_rdr) R_77PD_Active_rdr = (11, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (11, Weapons.K_77M_Active_Rdr) K_77M_Active_Rdr = (11, Su57Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (11, Weapons.KS_172_Passive_Rdr) KS_172_Passive_Rdr = (11, Su57Weapons.KS_172_Passive_Rdr)
Fuel_tank_800L_Wing = (11, Weapons.Fuel_tank_800L_Wing)
Su_57_Fuel_Tank = (11, Su57Weapons.Su_57_Fuel_Tank)
RN_28___260_kg__nuclear_bomb__free_fall = ( RN_28___260_kg__nuclear_bomb__free_fall = (
11, 11,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall, Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
) )
Smoke_Generator___red = (11, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (11, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (11, Weapons.Smoke_Generator___blue)
Smoke_Generator___white = (11, Weapons.Smoke_Generator___white)
Smoke_Generator___yellow = (11, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (11, Weapons.Smoke_Generator___orange)
Kh_59MK2 = (11, Su57Weapons.Kh_59MK2)
class Pylon12: class Pylon12:
R_73__AA_11_Archer____Infra_Red = (12, Weapons.R_73__AA_11_Archer____Infra_Red) R_73__AA_11_Archer____Infra_Red = (12, Weapons.R_73__AA_11_Archer____Infra_Red)
R_77PD_Active_rdr = (12, Su57Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (12, Su57Weapons.K_77M_Active_Rdr)
Smoke_Generator___red = (12, Weapons.Smoke_Generator___red) Smoke_Generator___red = (12, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (12, Weapons.Smoke_Generator___green) Smoke_Generator___green = (12, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (12, Weapons.Smoke_Generator___blue) Smoke_Generator___blue = (12, Weapons.Smoke_Generator___blue)
@@ -447,140 +557,7 @@ class Su_57(PlaneType):
Smoke_Generator___yellow = (12, Weapons.Smoke_Generator___yellow) Smoke_Generator___yellow = (12, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (12, Weapons.Smoke_Generator___orange) Smoke_Generator___orange = (12, Weapons.Smoke_Generator___orange)
class Pylon13: pylons: Set[int] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
R_27R__AA_10_Alamo_A____Semi_Act_Rdr = (
13,
Weapons.R_27R__AA_10_Alamo_A____Semi_Act_Rdr,
)
R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range = (
13,
Weapons.R_27ER__AA_10_Alamo_C____Semi_Act_Extended_Range,
)
R_27T__AA_10_Alamo_B____Infra_Red = (
13,
Weapons.R_27T__AA_10_Alamo_B____Infra_Red,
)
R_27ET__AA_10_Alamo_D____IR_Extended_Range = (
13,
Weapons.R_27ET__AA_10_Alamo_D____IR_Extended_Range,
)
R_77__AA_12_Adder____Active_Rdr = (13, Weapons.R_77__AA_12_Adder____Active_Rdr)
R_73__AA_11_Archer____Infra_Red = (13, Weapons.R_73__AA_11_Archer____Infra_Red)
Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr = (
13,
Weapons.Kh_31P__AS_17_Krypton____600kg__ARM__IN__Pas_Rdr,
)
Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr = (
13,
Weapons.Kh_31A__AS_17_Krypton____610kg__AShM__IN__Act_Rdr,
)
Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_ = (
13,
Weapons.Kh_29L__AS_14_Kedge____657kg__ASM__Semi_Act_Laser_,
)
Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_ = (
13,
Weapons.Kh_29T__AS_14_Kedge____670kg__ASM__TV_Guided_,
)
Kh_59M__AS_18_Kazoo____930kg__ASM__IN = (
13,
Weapons.Kh_59M__AS_18_Kazoo____930kg__ASM__IN,
)
MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD = (
13,
Weapons.MBD3_U6_68___6_x_OFAB_100_120___100_kg_GP_Bomb_LD,
)
B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag = (
13,
Weapons.B_8M1___20_x_UnGd_Rkts__80_mm_S_8KOM_HEAT_Frag,
)
B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation = (
13,
Weapons.B_13L___5_x_UnGd_Rkts__122_mm_S_13OF_Blast_Fragmentation,
)
O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator = (
13,
Weapons.O_25___1_x_UnGd_Rkts__340_mm_S_25_OFM_Hardened_Target_Penetrator,
)
BetAB_500___500_kg_Concrete_Piercing_Bomb_LD = (
13,
Weapons.BetAB_500___500_kg_Concrete_Piercing_Bomb_LD,
)
KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag = (
13,
Weapons.KMGU_2___96_x_AO_2_5RT_Dispenser__CBU__HE_Frag,
)
KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP = (
13,
Weapons.KMGU_2___96_x_PTAB_2_5KO_Dispenser__CBU__HEAT_AP,
)
OFAB_250_270___250_kg_GP_Bomb_LD = (
13,
Weapons.OFAB_250_270___250_kg_GP_Bomb_LD,
)
RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP = (
13,
Weapons.RBK_250___42_x_PTAB_2_5M__250kg_CBU_Medium_HEAT_AP,
)
FAB_500M_62___500_kg_GP_Bomb_LD = (13, Weapons.FAB_500M_62___500_kg_GP_Bomb_LD)
RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP = (
13,
Weapons.RBK_500_255___30_x_PTAB_10_5__500kg_CBU_Heavy_HEAT_AP,
)
KAB_500LG___500kg_Laser_Guided_Bomb = (
13,
Weapons.KAB_500LG___500kg_Laser_Guided_Bomb,
)
KAB_500Kr___500kg_TV_Guided_Bomb = (
13,
Weapons.KAB_500Kr___500kg_TV_Guided_Bomb,
)
FAB_1500_M_54___1500kg_GP_Bomb_LD = (
13,
Weapons.FAB_1500_M_54___1500kg_GP_Bomb_LD,
)
KAB_1500L___1500kg_Laser_Guided_Bomb = (
13,
Weapons.KAB_1500L___1500kg_Laser_Guided_Bomb,
)
MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD = (
13,
Weapons.MBD3_U6_68___6_x_OFAB_250_270___250_kg_GP_Bomb_LD,
)
# ERRR {R-33}
R_37M_Active_Rdr = (13, Weapons.R_37M_Active_Rdr)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (13, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (13, Weapons.K_77M_Active_Rdr)
KS_172_Passive_Rdr = (13, Weapons.KS_172_Passive_Rdr)
Fuel_tank_800L_Wing = (13, Weapons.Fuel_tank_800L_Wing)
RN_28___260_kg__nuclear_bomb__free_fall = (
13,
Weapons.RN_28___260_kg__nuclear_bomb__free_fall,
)
Smoke_Generator___red = (13, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (13, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (13, Weapons.Smoke_Generator___blue)
Smoke_Generator___white = (13, Weapons.Smoke_Generator___white)
Smoke_Generator___yellow = (13, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (13, Weapons.Smoke_Generator___orange)
class Pylon14:
R_73__AA_11_Archer____Infra_Red = (14, Weapons.R_73__AA_11_Archer____Infra_Red)
# ERRR {RVV-AE}
R_77PD_Active_rdr = (14, Weapons.R_77PD_Active_rdr)
K_77M_Active_Rdr = (14, Weapons.K_77M_Active_Rdr)
Smoke_Generator___red = (14, Weapons.Smoke_Generator___red)
Smoke_Generator___green = (14, Weapons.Smoke_Generator___green)
Smoke_Generator___blue = (14, Weapons.Smoke_Generator___blue)
Smoke_Generator___white = (14, Weapons.Smoke_Generator___white)
Smoke_Generator___yellow = (14, Weapons.Smoke_Generator___yellow)
Smoke_Generator___orange = (14, Weapons.Smoke_Generator___orange)
class Pylon15:
Mercury_LLTV_Pod = (15, Weapons.Mercury_LLTV_Pod)
pylons: Set[int] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
tasks = [ tasks = [
task.CAP, task.CAP,

View File

@@ -172,17 +172,6 @@ class PackageModel(QAbstractListModel):
else: else:
flight.abort() flight.abort()
EventStream.put_nowait(GameUpdateEvents().update_flight(flight)) EventStream.put_nowait(GameUpdateEvents().update_flight(flight))
# If there are no more flights in the package, delete the package.
if len(self.package.flights) == 0:
# Check if package is in ATO first as flight may still be "tentative" i.e.
# not added to the ATO yet.
if flight.package in flight.squadron.coalition.ato.packages:
flight.squadron.coalition.ato.remove_package(flight.package)
# Update ATO model so packages list is refreshed.
is_player = flight.squadron.coalition.player
self.game_model.ato_model_for(is_player).replace_from_game(
is_player
)
def delete_flight(self, flight: Flight) -> None: def delete_flight(self, flight: Flight) -> None:
"""Removes the given flight from the package.""" """Removes the given flight from the package."""
@@ -317,12 +306,9 @@ class AtoModel(QAbstractListModel):
index = self.ato.packages.index(package) index = self.ato.packages.index(package)
self.beginRemoveRows(QModelIndex(), index, index) self.beginRemoveRows(QModelIndex(), index, index)
for flight in package.flights: for flight in package.flights:
# Check if flight.callsign is None to handle case where callsign was not generated. self.game_model.game.blue.callsign_generator.release_callsign(
# This can happen when a module does not support the standard callsigns e.g. Kiowa. flight.callsign
if flight.callsign is not None: )
self.game_model.game.blue.callsign_generator.release_callsign(
flight.callsign
)
self.ato.remove_package(package) self.ato.remove_package(package)
self.endRemoveRows() self.endRemoveRows()
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences

View File

@@ -65,17 +65,14 @@ class QTimeTurnWidget(QGroupBox):
else: else:
self.set_date_and_time(time) self.set_date_and_time(time)
def set_current_turn( def set_current_turn(self, turn: int, conditions: Conditions) -> None:
self, turn: int, conditions: Conditions, time: datetime
) -> None:
"""Sets the turn information display. """Sets the turn information display.
:arg turn Current turn number. :arg turn Current turn number.
:arg conditions Current weather conditions. :arg conditions Current time and weather conditions.
:arg time Current time.
""" """
self.daytime_icon.setPixmap(self.icons[conditions.time_of_day]) self.daytime_icon.setPixmap(self.icons[conditions.time_of_day])
self.set_date_and_time(time) self.set_date_and_time(conditions.start_time)
self.setTitle(f"Turn {turn}") self.setTitle(f"Turn {turn}")
def set_date_and_time(self, time: datetime) -> None: def set_date_and_time(self, time: datetime) -> None:
@@ -308,15 +305,12 @@ class QConditionsWidget(QFrame):
self.weather_widget.hide() self.weather_widget.hide()
self.layout.addWidget(self.weather_widget, 0, 1) self.layout.addWidget(self.weather_widget, 0, 1)
def setCurrentTurn( def setCurrentTurn(self, turn: int, conditions: Conditions) -> None:
self, turn: int, conditions: Conditions, time: datetime | None
) -> None:
"""Sets the turn information display. """Sets the turn information display.
:arg turn Current turn number. :arg turn Current turn number.
:arg conditions Current weather conditions. :arg conditions Current time and weather conditions.
:arg time Current time.
""" """
self.time_turn_widget.set_current_turn(turn, conditions, time) self.time_turn_widget.set_current_turn(turn, conditions)
self.weather_widget.setCurrentTurn(turn, conditions) self.weather_widget.setCurrentTurn(turn, conditions)
self.weather_widget.show() self.weather_widget.show()

View File

@@ -50,7 +50,10 @@ class QTopPanel(QFrame):
self.conditionsWidget = QConditionsWidget(sim_controller) self.conditionsWidget = QConditionsWidget(sim_controller)
self.budgetBox = QBudgetBox(self.game) self.budgetBox = QBudgetBox(self.game)
self.passTurnButton = QPushButton(self._pass_turn_button_text(self.game)) pass_turn_text = "Pass Turn"
if not self.game or self.game.turn == 0:
pass_turn_text = "Begin Campaign"
self.passTurnButton = QPushButton(pass_turn_text)
self.passTurnButton.setIcon(CONST.ICONS["PassTurn"]) self.passTurnButton.setIcon(CONST.ICONS["PassTurn"])
self.passTurnButton.setProperty("style", "btn-primary") self.passTurnButton.setProperty("style", "btn-primary")
self.passTurnButton.clicked.connect(self.passTurn) self.passTurnButton.clicked.connect(self.passTurn)
@@ -101,9 +104,7 @@ class QTopPanel(QFrame):
if game is None: if game is None:
return return
self.conditionsWidget.setCurrentTurn( self.conditionsWidget.setCurrentTurn(game.turn, game.conditions)
game.turn, game.conditions, game.simulation_time
)
if game.conditions.weather.clouds: if game.conditions.weather.clouds:
base_m = game.conditions.weather.clouds.base base_m = game.conditions.weather.clouds.base
@@ -117,9 +118,11 @@ class QTopPanel(QFrame):
self.factionsInfos.setGame(game) self.factionsInfos.setGame(game)
self.passTurnButton.setEnabled(True) self.passTurnButton.setEnabled(True)
self.passTurnButton.setText(self._pass_turn_button_text(game)) if game and game.turn > 0:
self.passTurnButton.setText("Pass Turn")
if game and game.turn == 0: if game and game.turn == 0:
self.passTurnButton.setText("Begin Campaign")
self.proceedButton.setEnabled(False) self.proceedButton.setEnabled(False)
else: else:
self.proceedButton.setEnabled(True) self.proceedButton.setEnabled(True)
@@ -278,11 +281,3 @@ class QTopPanel(QFrame):
def budget_update(self, game: Game): def budget_update(self, game: Game):
self.budgetBox.setGame(game) self.budgetBox.setGame(game)
def _pass_turn_button_text(self, game: Game) -> None:
if game and game.turn > 0:
if game.settings.turnless_mode:
return "End Turn"
else:
return "Pass Turn"
return "Begin campaign"

View File

@@ -571,8 +571,7 @@ class QLiberationWindow(QMainWindow):
if state is not TurnState.CONTINUE: if state is not TurnState.CONTINUE:
GameOverDialog(won=state is TurnState.WIN, parent=self).exec() GameOverDialog(won=state is TurnState.WIN, parent=self).exec()
else: else:
if not self.game.settings.turnless_mode: self.game.pass_turn()
self.game.pass_turn()
GameUpdateSignal.get_instance().updateGame(self.game) GameUpdateSignal.get_instance().updateGame(self.game)
def open_tgo_info_dialog(self, tgo: TheaterGroundObject) -> None: def open_tgo_info_dialog(self, tgo: TheaterGroundObject) -> None:

View File

@@ -23,7 +23,6 @@ from game.theater import ControlPoint, TheaterGroundObject
from game.theater.theatergroundobject import ( from game.theater.theatergroundobject import (
BuildingGroundObject, BuildingGroundObject,
) )
from game.theater.theatergroup import TheaterUnit
from game.utils import Heading from game.utils import Heading
from qt_ui.uiconstants import EVENT_ICONS, ICONS from qt_ui.uiconstants import EVENT_ICONS, ICONS
from qt_ui.widgets.QBudgetBox import QBudgetBox from qt_ui.widgets.QBudgetBox import QBudgetBox
@@ -230,11 +229,10 @@ class QGroundObjectMenu(QDialog):
if self.sell_all_button is not None: if self.sell_all_button is not None:
self.sell_all_button.setText("Disband (+$" + str(self.total_value) + "M)") self.sell_all_button.setText("Disband (+$" + str(self.total_value) + "M)")
def repair_unit(self, unit: TheaterUnit, price: float): def repair_unit(self, unit, price):
if self.game.blue.budget > price: if self.game.blue.budget > price:
self.game.blue.budget -= price self.game.blue.budget -= price
unit.alive = True unit.alive = True
unit.hit_points = unit.unit_type.hit_points # Restore unit health to full
GameUpdateSignal.get_instance().updateGame(self.game) GameUpdateSignal.get_instance().updateGame(self.game)
# Remove destroyed units in the vicinity # Remove destroyed units in the vicinity

View File

@@ -843,7 +843,7 @@ class GeneratorOptions(QtWidgets.QWizardPage):
modLayout = QtWidgets.QGridLayout() modLayout = QtWidgets.QGridLayout()
modLayout_row = 1 modLayout_row = 1
modLayout.addWidget( modLayout.addWidget(
QtWidgets.QLabel("A-4E Skyhawk (version 2.3.0)"), modLayout_row, 0 QtWidgets.QLabel("A-4E Skyhawk (version 2.2.0)"), modLayout_row, 0
) )
modLayout.addWidget(a4_skyhawk, modLayout_row, 1) modLayout.addWidget(a4_skyhawk, modLayout_row, 1)
modLayout_row += 1 modLayout_row += 1

View File

@@ -36,8 +36,8 @@ pre-commit==3.5.0
pydantic==2.5.2 pydantic==2.5.2
pydantic-settings==2.1.0 pydantic-settings==2.1.0
pydantic_core==2.14.5 pydantic_core==2.14.5
pydcs @ git+https://github.com/dcs-liberation/dcs@046ed928de5d4aae1652251b87e46517ab334f6e pydcs @ git+https://github.com/dcs-liberation/dcs@0a44d7ec87ffa7ab4fea4a17cd0d3ac44bcc85e5
pyinstaller==6.0.0 pyinstaller==5.13.1
pyinstaller-hooks-contrib==2023.6 pyinstaller-hooks-contrib==2023.6
pyproj==3.6.1 pyproj==3.6.1
PySide6==6.4.1 PySide6==6.4.1

View File

@@ -178,15 +178,15 @@ local unitPayloads = {
["name"] = "Liberation SEAD", ["name"] = "Liberation SEAD",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}", ["CLSID"] = "{AGM_45A}",
["num"] = 5, ["num"] = 5,
}, },
[2] = { [2] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}", ["CLSID"] = "{AGM_45A}",
["num"] = 1, ["num"] = 1,
}, },
[3] = { [3] = {
["CLSID"] = "<CLEAN>", ["CLSID"] = "{AGM_45A}",
["num"] = 4, ["num"] = 4,
}, },
[4] = { [4] = {
@@ -194,7 +194,7 @@ local unitPayloads = {
["num"] = 3, ["num"] = 3,
}, },
[5] = { [5] = {
["CLSID"] = "<CLEAN>", ["CLSID"] = "{AGM_45A}",
["num"] = 2, ["num"] = 2,
}, },
}, },
@@ -265,15 +265,15 @@ local unitPayloads = {
["name"] = "Liberation SEAD Escort", ["name"] = "Liberation SEAD Escort",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}", ["CLSID"] = "{AGM_45A}",
["num"] = 5, ["num"] = 5,
}, },
[2] = { [2] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}", ["CLSID"] = "{AGM_45A}",
["num"] = 1, ["num"] = 1,
}, },
[3] = { [3] = {
["CLSID"] = "<CLEAN>", ["CLSID"] = "{AGM_45A}",
["num"] = 4, ["num"] = 4,
}, },
[4] = { [4] = {
@@ -281,7 +281,7 @@ local unitPayloads = {
["num"] = 3, ["num"] = 3,
}, },
[5] = { [5] = {
["CLSID"] = "<CLEAN>", ["CLSID"] = "{AGM_45A}",
["num"] = 2, ["num"] = 2,
}, },
}, },
@@ -352,11 +352,11 @@ local unitPayloads = {
["name"] = "Liberation DEAD", ["name"] = "Liberation DEAD",
["pylons"] = { ["pylons"] = {
[1] = { [1] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}", ["CLSID"] = "{AGM_45A}",
["num"] = 5, ["num"] = 5,
}, },
[2] = { [2] = {
["CLSID"] = "{C_A4E_AGM-45B_LAU34}", ["CLSID"] = "{AGM_45A}",
["num"] = 1, ["num"] = 1,
}, },
[3] = { [3] = {

View File

@@ -1,344 +0,0 @@
local unitPayloads = {
["name"] = "F-14A",
["payloads"] = {
[1] = {
["name"] = "CAP",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 L}",
["num"] = 2,
},
[4] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 R}",
["num"] = 9,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{AIM_54C_Mk47}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{AIM_54C_Mk47}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{AIM_54C_Mk47}",
["num"] = 6,
},
[10] = {
["CLSID"] = "{AIM_54C_Mk47}",
["num"] = 5,
},
},
["tasks"] = {
[1] = 10,
},
},
[2] = {
["name"] = "CAS",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{F14-LANTIRN-TP}",
["num"] = 9,
},
[4] = {
["CLSID"] = "{PHXBRU3242_2*LAU10 LS}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 6,
},
[10] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 5,
},
},
["tasks"] = {
[1] = 10,
},
},
[3] = {
["name"] = "STRIKE",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{F14-LANTIRN-TP}",
["num"] = 9,
},
[4] = {
["CLSID"] = "{SHOULDER AIM-7MH}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 6,
},
[10] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 5,
},
},
["tasks"] = {
[1] = 10,
},
},
[4] = {
["name"] = "BAI",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{F14-LANTIRN-TP}",
["num"] = 9,
},
[4] = {
["CLSID"] = "{PHXBRU3242_2*LAU10 LS}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{BRU-32 MK-82}",
["num"] = 4,
},
[9] = {
["CLSID"] = "{BRU-32 MK-20}",
["num"] = 6,
},
[10] = {
["CLSID"] = "{BRU-32 MK-20}",
["num"] = 5,
},
},
["tasks"] = {
[1] = 10,
},
},
[5] = {
["name"] = "ANTISHIP",
["pylons"] = {
[1] = {
["CLSID"] = "{F14-LANTIRN-TP}",
["num"] = 9,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[3] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[4] = {
["CLSID"] = "{PHXBRU3242_2*LAU10 LS}",
["num"] = 2,
},
[5] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 7,
},
[6] = {
["CLSID"] = "{BRU-32 GBU-16}",
["num"] = 4,
},
[7] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 6,
},
[8] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 5,
},
[9] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[10] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
},
["tasks"] = {
[1] = 10,
},
},
[6] = {
["name"] = "Liberation DEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 L}",
["num"] = 2,
},
[4] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 R}",
["num"] = 9,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{MAK79_MK82 4}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{MAK79_MK82 3R}",
["num"] = 6,
},
[9] = {
["CLSID"] = "{MAK79_MK82 3L}",
["num"] = 5,
},
[10] = {
["CLSID"] = "{MAK79_MK82 4}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 31,
},
},
[7] = {
["displayName"] = "Liberation SEAD",
["name"] = "Liberation SEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 10,
},
[2] = {
["CLSID"] = "{LAU-138 wtip - AIM-9M}",
["num"] = 1,
},
[3] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 L}",
["num"] = 2,
},
[4] = {
["CLSID"] = "{SHOULDER AIM_54C_Mk47 R}",
["num"] = 9,
},
[5] = {
["CLSID"] = "{F14-300gal}",
["num"] = 8,
},
[6] = {
["CLSID"] = "{F14-300gal}",
["num"] = 3,
},
[7] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 7,
},
[8] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 6,
},
[9] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 5,
},
[10] = {
["CLSID"] = "{BRU3242_ADM141}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 31,
},
},
},
["unitType"] = "F-14A-135-GR-Early",
}
return unitPayloads

View File

@@ -1,224 +0,0 @@
local unitPayloads = {
["name"] = "MiG-29A",
["payloads"] = {
[1] = {
["name"] = "CAS",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
[2] = {
["CLSID"] = "B-8M1 - 20 S-8OFP2",
["num"] = 5,
},
[3] = {
["CLSID"] = "B-8M1 - 20 S-8OFP2",
["num"] = 6,
},
[4] = {
["CLSID"] = "B-8M1 - 20 S-8OFP2",
["num"] = 3,
},
[5] = {
["CLSID"] = "B-8M1 - 20 S-8OFP2",
["num"] = 2,
},
[6] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[7] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 30,
},
},
[2] = {
["name"] = "STRIKE",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[2] = {
["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}",
["num"] = 2,
},
[3] = {
["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
[5] = {
["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}",
["num"] = 5,
},
[6] = {
["CLSID"] = "{37DCC01E-9E02-432F-B61D-10C166CA2798}",
["num"] = 6,
},
[7] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
},
["tasks"] = {
[1] = 32,
},
},
[3] = {
["name"] = "CAP",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[2] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 2,
},
[3] = {
["CLSID"] = "{9B25D316-0434-4954-868F-D51DB1A38DF0}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{9B25D316-0434-4954-868F-D51DB1A38DF0}",
["num"] = 5,
},
[5] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 6,
},
[6] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
[7] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 10,
},
},
[4] = {
["name"] = "ANTISHIP",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
[2] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 5,
},
[3] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 6,
},
[4] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 3,
},
[5] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 2,
},
[6] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[7] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 30,
},
},
[5] = {
["name"] = "SEAD",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
[2] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 5,
},
[3] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 6,
},
[4] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 3,
},
[5] = {
["CLSID"] = "{3858707D-F5D5-4bbb-BDD8-ABB0530EBC7C}",
["num"] = 2,
},
[6] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[7] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
},
["tasks"] = {
[1] = 30,
},
},
[6] = {
["displayName"] = "OCA/Runway",
["name"] = "OCA/Runway",
["pylons"] = {
[1] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 1,
},
[2] = {
["CLSID"] = "{BD289E34-DF84-4C5E-9220-4B14C346E79D}",
["num"] = 2,
},
[3] = {
["CLSID"] = "{BD289E34-DF84-4C5E-9220-4B14C346E79D}",
["num"] = 3,
},
[4] = {
["CLSID"] = "{PTB_1500_MIG29A}",
["num"] = 4,
},
[5] = {
["CLSID"] = "{BD289E34-DF84-4C5E-9220-4B14C346E79D}",
["num"] = 5,
},
[6] = {
["CLSID"] = "{BD289E34-DF84-4C5E-9220-4B14C346E79D}",
["num"] = 6,
},
[7] = {
["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}",
["num"] = 7,
},
},
["tasks"] = {
[1] = 34,
},
},
},
["unitType"] = "MiG-29 Fulcrum",
}
return unitPayloads

View File

@@ -6,8 +6,6 @@ max_ingress_distance_nm: 30
min_ingress_distance_nm: 10 min_ingress_distance_nm: 10
rendezvous_altitude_ft_msl: 22000 rendezvous_altitude_ft_msl: 22000
combat_altitude_ft_msl: 18000 combat_altitude_ft_msl: 18000
aewc:
duration_minutes: 240
cap: cap:
duration_minutes: 30 duration_minutes: 30
min_track_length_nm: 12 min_track_length_nm: 12

View File

@@ -6,8 +6,6 @@ max_ingress_distance_nm: 45
min_ingress_distance_nm: 10 min_ingress_distance_nm: 10
rendezvous_altitude_ft_msl: 25000 rendezvous_altitude_ft_msl: 25000
combat_altitude_ft_msl: 20000 combat_altitude_ft_msl: 20000
aewc:
duration_minutes: 240
cap: cap:
duration_minutes: 30 duration_minutes: 30
min_track_length_nm: 15 min_track_length_nm: 15

View File

@@ -6,8 +6,6 @@ max_ingress_distance_nm: 7
min_ingress_distance_nm: 5 min_ingress_distance_nm: 5
rendezvous_altitude_ft_msl: 10000 rendezvous_altitude_ft_msl: 10000
combat_altitude_ft_msl: 8000 combat_altitude_ft_msl: 8000
aewc:
duration_minutes: 240
cap: cap:
duration_minutes: 30 duration_minutes: 30
min_track_length_nm: 8 min_track_length_nm: 8

View File

@@ -14,7 +14,6 @@ aircrafts:
- C-130 - C-130
- C-130J-30 Super Hercules - C-130J-30 Super Hercules
- F-117A Nighthawk - F-117A Nighthawk
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat - F-14B Tomcat
- F-15C Eagle - F-15C Eagle

View File

@@ -15,7 +15,6 @@ aircrafts:
- C-130 - C-130
- C-130J-30 Super Hercules - C-130J-30 Super Hercules
- F-117A Nighthawk - F-117A Nighthawk
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat - F-14B Tomcat
- F-15C Eagle - F-15C Eagle

View File

@@ -10,7 +10,6 @@ aircrafts:
- B-52H Stratofortress - B-52H Stratofortress
- C-130 - C-130
- C-130J-30 Super Hercules - C-130J-30 Super Hercules
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat - F-14B Tomcat
- F-4E-45MC Phantom II - F-4E-45MC Phantom II

View File

@@ -17,7 +17,6 @@ aircrafts:
- C-47 Dakota - C-47 Dakota
- CH-47D - CH-47D
- CH-53E - CH-53E
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat - F-14B Tomcat
- F-15C Eagle - F-15C Eagle

View File

@@ -7,7 +7,6 @@ locales:
- fa_IR - fa_IR
aircrafts: aircrafts:
- AH-1J SeaCobra - AH-1J SeaCobra
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-4E-45MC Phantom II - F-4E-45MC Phantom II
- F-5E Tiger II - F-5E Tiger II

View File

@@ -6,7 +6,6 @@ description: <p>Iranian 2010s faction</p>
locales: locales:
- fa_IR - fa_IR
aircrafts: aircrafts:
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-4E-45MC Phantom II - F-4E-45MC Phantom II
- F-5E Tiger II - F-5E Tiger II
@@ -15,7 +14,6 @@ aircrafts:
- Mi-24P Hind-F - Mi-24P Hind-F
- Mi-28N Havoc - Mi-28N Havoc
- MiG-21bis Fishbed-N - MiG-21bis Fishbed-N
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A - MiG-29A Fulcrum-A
- Mirage-F1EQ - Mirage-F1EQ
- Su-22M4 Fitter-K - Su-22M4 Fitter-K

View File

@@ -13,7 +13,6 @@ aircrafts:
- MiG-21bis Fishbed-N - MiG-21bis Fishbed-N
- MiG-23ML Flogger-G - MiG-23ML Flogger-G
- MiG-25PD Foxbat-E - MiG-25PD Foxbat-E
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A - MiG-29A Fulcrum-A
- Mirage-F1EQ - Mirage-F1EQ
- SA 342M Gazelle - SA 342M Gazelle

View File

@@ -11,7 +11,6 @@ aircrafts:
- MiG-19P Farmer-B - MiG-19P Farmer-B
- MiG-21bis Fishbed-N - MiG-21bis Fishbed-N
- MiG-23MLD Flogger-K - MiG-23MLD Flogger-K
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A - MiG-29A Fulcrum-A
awacs: awacs:
- A-50 - A-50

View File

@@ -10,7 +10,6 @@ aircrafts:
- Mi-24V Hind-E - Mi-24V Hind-E
- Mi-24P Hind-F - Mi-24P Hind-F
- Mi-8MTV2 Hip - Mi-8MTV2 Hip
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A - MiG-29A Fulcrum-A
- MiG-29G Fulcrum-A - MiG-29G Fulcrum-A
- Su-22M4 Fitter-K - Su-22M4 Fitter-K

View File

@@ -13,7 +13,6 @@ aircrafts:
- MiG-21bis Fishbed-N - MiG-21bis Fishbed-N
- MiG-23MLD Flogger-K - MiG-23MLD Flogger-K
- MiG-25PD Foxbat-E - MiG-25PD Foxbat-E
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A - MiG-29A Fulcrum-A
- Su-17M4 Fitter-K - Su-17M4 Fitter-K
- Su-24M Fencer-D - Su-24M Fencer-D

View File

@@ -14,7 +14,6 @@ aircrafts:
- MiG-23MLD Flogger-K - MiG-23MLD Flogger-K
- MiG-25PD Foxbat-E - MiG-25PD Foxbat-E
- MiG-27K Flogger-J2 - MiG-27K Flogger-J2
- MIG-29-FULCRUM
- MiG-29A Fulcrum-A - MiG-29A Fulcrum-A
- MiG-31 Foxhound - MiG-31 Foxhound
- Su-17M4 Fitter-K - Su-17M4 Fitter-K

View File

@@ -6,7 +6,6 @@ description: <p>US military during the Vietnam War from 1965 to 1975</p>
locales: locales:
- en_US - en_US
aircrafts: aircrafts:
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-4C Phantom II - F-4C Phantom II
- F-4B Phantom II - F-4B Phantom II

View File

@@ -10,7 +10,6 @@ aircrafts:
- C-130 - C-130
- CH-47D - CH-47D
- CH-53E - CH-53E
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-4E-45MC Phantom II - F-4E-45MC Phantom II
- F-4B Phantom II - F-4B Phantom II

View File

@@ -16,7 +16,6 @@ aircrafts:
- CH-47D - CH-47D
- CH-53E - CH-53E
- F-117A Nighthawk - F-117A Nighthawk
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat - F-14B Tomcat
- F-15C Eagle - F-15C Eagle

View File

@@ -8,7 +8,6 @@ locales:
aircrafts: aircrafts:
- AH-1W SuperCobra - AH-1W SuperCobra
- A-4E Skyhawk - A-4E Skyhawk
- F-14A Tomcat (Block 135-GR Early)
- F-14A Tomcat (Block 135-GR Late) - F-14A Tomcat (Block 135-GR Late)
- F-14B Tomcat - F-14B Tomcat
- F-4B Phantom II - F-4B Phantom II

View File

@@ -4,7 +4,6 @@ local WRITESTATE_SCHEDULE_IN_SECONDS = 60
logger = mist.Logger:new("DCSLiberation", "info") logger = mist.Logger:new("DCSLiberation", "info")
logger:info("Check that json.lua is loaded : json = "..tostring(json)) logger:info("Check that json.lua is loaded : json = "..tostring(json))
simulation_time_seconds = 0
crash_events = {} -- killed aircraft will be added via S_EVENT_CRASH event crash_events = {} -- killed aircraft will be added via S_EVENT_CRASH event
dead_events = {} -- killed units will be added via S_EVENT_DEAD event dead_events = {} -- killed units will be added via S_EVENT_DEAD event
unit_lost_events = {} -- killed units will be added via S_EVENT_UNIT_LOST unit_lost_events = {} -- killed units will be added via S_EVENT_UNIT_LOST
@@ -44,7 +43,6 @@ function write_state()
["destroyed_objects_positions"] = destroyed_objects_positions, ["destroyed_objects_positions"] = destroyed_objects_positions,
["killed_ground_units"] = killed_ground_units, ["killed_ground_units"] = killed_ground_units,
["unit_hit_point_updates"] = unit_hit_point_updates, ["unit_hit_point_updates"] = unit_hit_point_updates,
["simulation_time_seconds"] = simulation_time_seconds
} }
if not json then if not json then
local message = string.format("Unable to save DCS Liberation state to %s, JSON library is not loaded !", _debriefing_file_location) local message = string.format("Unable to save DCS Liberation state to %s, JSON library is not loaded !", _debriefing_file_location)
@@ -162,9 +160,6 @@ end
activeWeapons = {} activeWeapons = {}
local function onEvent(event) local function onEvent(event)
simulation_time_seconds = event.time
if event.id == world.event.S_EVENT_CRASH and event.initiator then if event.id == world.event.S_EVENT_CRASH and event.initiator then
crash_events[#crash_events + 1] = event.initiator.getName(event.initiator) crash_events[#crash_events + 1] = event.initiator.getName(event.initiator)
write_state() write_state()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,62 +0,0 @@
carrier_capable: true
description:
"The Grumman F-14 Tomcat is a two-crew, variable wing-geometry, maritime\
\ air superiority fighter that served with the US Navy for 32 years and continues\
\ to serve with the IRIAF in Iran. The F-14 was the US Navy's frontline fighter\
\ from the 1970s to the mid-2000s. Over the course of its long service it also became\
\ one of the US Navy\u2019s premier precision ground-attack platform and its lone\
\ airborne reconnaissance asset.\n\nNoteworthy features of the Tomcat are its swing-wing\
\ configuration, two-man crew, and the powerful AN/AWG-9 Weapons Control System\
\ (WCS) and radar. The AWG-9 allows employment of the long-range AIM-54 Phoenix\
\ air-to-air missile, and the LANTIRN targeting pod allows precision ground strikes\
\ using laser-guided bombs. The F-14 Tomcat was present in several historic events\
\ that include the two Gulf of Sidra incidents, Operations Desert Storm Iraqi Freedom,\
\ the Yugoslavian conflict, and Operation Enduring Freedom over Afghanistan. It\
\ was also immortalized in the iconic motion picture, Top Gun, and starred in several\
\ other feature films including The Final Countdown, Executive Decision, and others.\n\
\nThe Tomcat was also played a vital role in the Iran-Iraq war of the 1980s, where\
\ is flew for the Islamic Republic of Iran Air Force."
introduced: 1984
manufacturer: Grumman
origin: USA
price: 22
role: Carrier-based Air-Superiority Fighter/Fighter Bomber
max_range: 350
variants:
F-14A Tomcat (Block 135-GR Early): {}
radios:
intra_flight: AN/ARC-182
inter_flight: AN/ARC-159
channels:
type: common
namer: tomcat
intra_flight_radio_index: 2
inter_flight_radio_index: 1
default_overrides:
INSAlignmentStored: true
# ALE39Loadout: 0
# IlsChannel: 1
# KY28Key: 1
# LGB1: 8
# LGB10: 8
# LGB100: 6
# LGB1000: 1
# M61BURST: 0
# TacanBand: 0
# TacanChannel: 0
# UseLAU138: true
tasks:
BAI: 630
BARCAP: 520
CAS: 630
DEAD: 240
Escort: 520
Fighter sweep: 520
Intercept: 520
OCA/Aircraft: 630
OCA/Runway: 550
SEAD: 90
SEAD Escort: 90
Strike: 550
TARCAP: 520
hit_points: 20

View File

@@ -1,52 +0,0 @@
description:
'The MiG-29 "Fulcrum" is a Russian-designed, twin-engine, supersonic
fighter. First operational in the early 1980s, the Fulcrum is a "light weight" fighter,
comparable to the American F/A-18 Hornet and F-16. Designed to work in conjunction
with the larger Su-27 Flanker, the MiG-29 is armed with an internal 30mm cannon
and both infrared and radar guided air-to-air missiles. For air-to-ground tasks,
the MiG-29 can be armed with a large array of unguided bombs and rockets.
In addition to a sophisticated pulse doppler radar, the MiG-29 is also equipped
with a passive Infrared Search and Track (IRST) sensor that allows the Fulcrum to
detect and target enemy aircraft just based on target infrared emissions. This allows
the MiG-29 to make stealthy attacks with no warning!
The Fulcrum is a highly-maneuverable fighter in a dogfight, and when paired with
the helmet mounted sight and the AA-11 "Archer" air-to-air missile, it is a very
lethal adversary.
The MiG-29 has also been widely exported and has served in many countries that include
Germany, Iran, Ukraine, and Poland.'
introduced: 1983
manufacturer: Mikoyan
origin: USSR/Russia
price: 15
role: Multirole Fighter
max_range: 150
variants:
MIG-29-FULCRUM:
display_name: MiG-29A Fulcrum-A
kneeboard_units: "metric"
radios:
intra_flight: R862
inter_flight: R862
channels:
type: common
namer: fulcrum
intra_flight_radio_index: 1
inter_flight_radio_index: 1
tasks:
BAI: 530
BARCAP: 370
CAS: 530
Escort: 370
Fighter sweep: 370
Intercept: 370
OCA/Aircraft: 530
OCA/Runway: 410
Strike: 410
TARCAP: 370
hit_points: 16

View File

@@ -27,8 +27,7 @@ price: 15
role: Multirole Fighter role: Multirole Fighter
max_range: 150 max_range: 150
variants: variants:
MiG-29A Fulcrum-A: MiG-29A Fulcrum-A: {}
display_name: MiG-29A Fulcrum-A (FC3)
kneeboard_units: "metric" kneeboard_units: "metric"
tasks: tasks:
BAI: 530 BAI: 530