174 Commits

Author SHA1 Message Date
valmojr 0486f2a285 Added initial COT Sensor payloads to support UAV Tools integration for Arma Drones 2026-04-13 08:03:31 -03:00
valmojr 753dcab26e Added hellanmaaw winter support 2026-03-31 07:23:48 -03:00
valmojr 2f53488ba8 Added video url prop to 3den editor/zeus, allowing to parse __video prop to cots 2026-03-31 07:21:29 -03:00
valmojr 323339e679 Removed video addon, too simple for a specific addon 2026-03-31 07:20:19 -03:00
valmojr 3f14a75e81 Added video url parser to CoT types 2026-03-31 07:19:39 -03:00
valmojr 469a54c141 Added Hellanmma map support 2026-03-31 07:18:23 -03:00
valmojr 2ee9030c00 Updated media folder 2026-03-26 14:45:08 -03:00
valmojr 5b29a40990 Improved mTLS description on readme 2026-03-26 03:47:54 -03:00
valmojr 708fe5e670 Fixed CoT queue during armatak connection to the TAK Server, running soft as butter 2026-03-26 03:45:05 -03:00
valmojr e32aadda4e Splitted Connection Module 2026-03-26 01:05:54 -03:00
valmojr c35b7f0268 Updated project readme file 2026-03-24 16:56:26 -03:00
valmojr 876cf900c3 Changed dialogs and module UI to get mTLS needed params 2026-03-24 16:56:19 -03:00
valmojr 778ac0ac54 Added the mTLS connection calls to zeus and 3den modules 2026-03-24 16:55:53 -03:00
valmojr b816144fb0 Added transport layer and configured extension commands to call mTLS socket connection 2026-03-24 16:55:36 -03:00
valmojr 61ba9f6d63 Added connector and enrollment for mTLS client certificate auto enrollment on game sessions, will MOCK a official tak client behavior when authenticating 2026-03-24 16:55:05 -03:00
valmojr f88c02a7aa formatted some rust files for linting porpuses 2026-03-24 16:44:22 -03:00
valmojr 5ffc08e6f1 Readded reqwest dependency to cargo toml, will be used for TAK Server API interaction on authencated tak server connections 2026-03-24 16:41:38 -03:00
valmojr 9392380c78 Added hemtt private key to git ignore 2026-03-24 16:40:58 -03:00
valmojr a18343b81d Commented video module 2026-03-24 14:03:28 -03:00
Valmo Trindade 13cd08c655 Added mandol map support 2026-01-03 02:55:39 -03:00
Valmo Trindade 8fe14dc18d Added Clafghan Map Support 2026-01-02 03:28:10 -03:00
Valmo Trindade 1bec26df8a Added UMP Colombia map support 2025-12-21 02:21:02 -03:00
Valmo Trindade c5d5da636f added malvinas pradero ganso function call 2025-12-13 15:00:33 -03:00
Valmo Trindade c2e137e67c Added lawn map 2025-12-13 14:59:05 -03:00
Valmo Trindade de5ac9dbb5 Added Malvinas Maps 2025-12-12 19:12:04 -03:00
Valmo Trindade ef3be1e768 fixed router entity remover function 2025-12-10 23:07:53 -03:00
Valmo Trindade 9bda92d389 Removed once cell dependency 2025-11-30 10:43:43 -03:00
Valmo Trindade 9763cb6697 reoganized command groups on extension call 2025-11-30 10:43:18 -03:00
Valmo Trindade 5ac49e12f8 customized sensor markers to dont cheat enemy info 2025-11-26 20:21:09 -03:00
Valmo Trindade 2108d20b01 changed default affiliation to be unkown 2025-11-26 20:20:51 -03:00
Valmo Trindade 524e7a0b3e Added vehicle sensor handler to get sensor input and throw it on ATAK 2025-11-22 12:15:15 -03:00
Valmo Trindade 7e4379ada4 Added enemy marker function to ease enemy marking 2025-11-20 04:51:10 -03:00
Valmo Trindade 572b2a360f ADded zagorsk reserverd forest map 2025-11-20 04:50:52 -03:00
Valmo Trindade 083ccd2906 Linted cot refresh rate 2025-11-15 06:56:47 -03:00
Valmo Trindade 35a45d2cd4 fixed drone handler 2025-11-15 06:48:03 -03:00
Valmo Trindade 2b241fbeaf Fixed extract position function and dependency chain 2025-11-15 01:57:23 -03:00
Valmo Trindade ad9ba834cc Merge pull request #22 from Roborob1234/patch-1
Update fn_convert_to_stratis.sqf
2025-10-18 02:29:58 -03:00
Rob Haddow 469403d9b5 Update fn_convert_to_stratis.sqf
[Fix] Corrected NW corner from my earlier work, NW corner had the Lat value of the S edge.
2025-10-17 19:28:17 -05:00
Valmo Trindade 01ea754f57 Merge pull request #21 from Roborob1234/Rob's-tinkering
Stratis and Tanoa coordinate update
2025-10-14 19:24:37 -03:00
Rob Haddow fd8a25790e Update fn_convert_to_stratis.sqf
Updated Stratis with in game map size and accurized map corners
2025-10-13 12:15:04 -05:00
Rob Haddow 9ede7237b8 Merge branch 'valmojr:main' into patch-2 2025-10-13 11:30:43 -05:00
Valmo Trindade 1242b1f79f Fixed drone params on callsign function 2025-10-12 20:44:38 -03:00
Valmo Trindade 9f8f326446 fixed params on log function 2025-10-12 20:44:25 -03:00
Valmo Trindade bf3b0cf0d4 Added ConfigOf props 2025-10-12 20:44:17 -03:00
Valmo Trindade 42098401f2 Fixed syntax on ConverClientPosition function 2025-10-12 20:43:36 -03:00
Valmo Trindade cad4aaa1a5 Added Tanoa to switch case function to manage positions 2025-10-12 20:31:00 -03:00
Roborob1234 ef787a6a09 Update fn_convert_to_tanoa.sqf
Updated Tanoa map size from Altis Default and changed IRL Map edges to align with results from US FCC lat lon calculator: https://www.fcc.gov/media/radio/dms-decimal
2025-10-12 18:14:49 -05:00
Valmo Trindade 2e017f97c9 Removed executable because brett said dont need it 2025-09-09 14:16:02 -03:00
Valmo Trindade fbd58d9426 Removed SIMTAK apk from includes, added executable for linux 2025-09-04 11:24:29 -03:00
Valmo Trindade 894a11f087 Removed FFMPEG Video Streaming support for now, it has many variables to deal with it yet 2025-07-30 23:10:55 -03:00
Valmo Trindade dacb38fe45 Added github action to push into production mod when a release is approved 2025-07-30 23:09:51 -03:00
Valmo Trindade 2298254e24 Changed UDP Socket bind address to match the LOCAL address and point to a LOCAL target address, this will fit 99% of the use cases and avoid many mistakes 2025-07-30 15:15:38 -03:00
Valmo Trindade 853000a5c9 fixed LFS images 2025-07-30 14:31:06 -03:00
Valmo Trindade d0b47dd315 changed arma 3 executable to fit my linux proton installation 2025-07-30 12:48:02 -03:00
Valmo Trindade 3c9dd1bea4 removed websocket component from extension part 2025-07-16 13:18:07 -03:00
Valmo Trindade 4d89ea7bc5 removed unused dialog imports 2025-07-16 13:05:02 -03:00
Valmo Trindade b97d13121e (WIP) refacotred video stream generator 2025-07-16 12:46:53 -03:00
Valmo Trindade dcfdb0451c removed stop UDP Socket function because it was not implemented, and will not be soo close 2025-07-16 12:46:43 -03:00
Valmo Trindade 83b9082e87 added end of line in all files 2025-07-16 12:46:12 -03:00
Valmo Trindade 2ab83a17b9 refactored lfs objects 2025-07-12 12:17:55 -03:00
Valmo Trindade 4ae35335e2 Added fail callback UDP switch to turn of config on clientside 2025-06-25 13:10:15 -03:00
Valmo Trindade a1bf9472ae added static video geoencoding to test KLV data 2025-06-24 19:34:08 -03:00
Valmo Trindade 15129bb344 removed useless mod metadata from addons/video config 2025-06-23 02:25:36 -03:00
Valmo Trindade f143d80c34 added more cool mod preset 2025-06-23 02:25:22 -03:00
Valmo Trindade e713c2f35f refactored video stream handler to handle RTSP feed on linux with multiple OS data, avoinding DRY 2025-06-19 23:44:19 -03:00
Valmo Trindade b1fac90e78 Switched release description to match the commit tag only 2025-06-19 20:25:20 -03:00
Valmo Trindade 8341288457 Removed unused mods to hemtt launcher 2025-06-17 23:35:02 -03:00
Valmo Trindade 4ad2b2d6dd Added video feed support for Linux clients 2025-06-17 05:21:11 -03:00
Valmo Trindade 485e67120c reduce the external gps position frequency to 2Hz 2025-06-17 05:16:32 -03:00
Valmo Trindade 60f04bc4e8 added start and stop functions for the UDP Socket 2025-06-17 03:57:23 -03:00
Valmo Trindade 35742847a7 linted extract group color function and parsed colors gvar 2025-06-17 03:57:13 -03:00
Valmo Trindade c8c2b639ea removed group info from client side, because sadly it won't work as a handler for it 2025-06-17 03:56:48 -03:00
Valmo Trindade 0453470f1f defined group colors as a init gvar 2025-06-17 03:54:56 -03:00
Valmo Trindade d9da877da6 added ace self action to create the eud connection dialog 2025-06-17 03:43:07 -03:00
Valmo Trindade ed2b09a5f6 defined rust as main language of the project 2025-06-17 03:42:36 -03:00
Valmo Trindade c1198ef287 added dialog to input data for eud connection 2025-06-17 03:42:26 -03:00
Valmo Trindade 58f6d3f349 removed unused imports on server dialogs 2025-06-17 03:42:15 -03:00
Valmo Trindade 67a7fa99af removed gradle config 2025-06-17 02:23:59 -03:00
Valmo Trindade 220c56f01d Removed SIMTAK for the workflows on GH actions 2025-06-17 02:23:40 -03:00
Valmo Trindade 30be943581 FINALLY removed the SIMTAK application for my project, it was a good start, but it's time to move on and i got it native on ATAK, thanks @Andonyth for the help 2025-06-17 02:12:28 -03:00
Valmo Trindade a859e55c1b Managed dependencies and remove many legacy features dependencies and unused stuff 2025-06-17 02:03:37 -03:00
Valmo Trindade f491b06664 Improved callbacks for UDP sockets 2025-06-17 01:54:30 -03:00
Valmo Trindade 874686c975 changed the extractClientPosition to fit the external gps use case 2025-06-17 01:42:37 -03:00
Valmo Trindade 2a7c1b8ae8 removed websocket stuff from the functions because i can make this go to the trash can 2025-06-17 01:41:50 -03:00
Valmo Trindade 8ddbefee18 Improved callback handlers to get UDP socket stuff 2025-06-17 01:41:22 -03:00
Valmo Trindade 2b190d72c5 fixed callsign function calls on cot generators 2025-06-17 01:40:49 -03:00
Valmo Trindade 9fb8311aca Added UDP Socket, because now i can mock a external GPS on EUD and that's awesome 2025-06-17 01:40:26 -03:00
Valmo Trindade d4f6ddb0fa linted linux block because now i actually have to care about linux 2025-06-17 01:38:43 -03:00
Valmo Trindade 0dd12a275b removed unused structs from root project 2025-06-17 01:38:12 -03:00
Valmo Trindade c45708066e renamed tcp socket folder for a name that actually makes any sense 2025-06-17 01:37:45 -03:00
Valmo Trindade 0de4cf75e8 Added GPS CoT Structs 2025-06-17 01:37:28 -03:00
Valmo Trindade 9bb4483266 linted digital pointer structs 2025-06-16 04:27:06 -03:00
Valmo Trindade ffc75cf4c4 added handler (personal) for the linux hemtt launch params 2025-06-16 04:26:55 -03:00
Valmo Trindade 2919805844 fixed uni callsign extraction on group cot sender 2025-06-16 04:26:15 -03:00
Valmo Trindade f3bff2b9cf Added Kunduz Valley Map Support 2025-06-01 04:19:35 -03:00
Valmo Trindade 74cda1c9a6 fixed extract position call on laser marker 2025-06-01 03:19:47 -03:00
Valmo Trindade 6c667d69b8 improved router entity add and remove function 2025-05-28 00:32:57 -03:00
Valmo Trindade 5f62304965 change if hell to switchcase on 3denCoremodule config func 2025-05-28 00:32:37 -03:00
Valmo Trindade 082831951e change if hell to switchcase on callback handlers func 2025-05-28 00:32:20 -03:00
Valmo Trindade 645a16394b change if hell to switchcase on zeusCoremodule config func 2025-05-28 00:32:00 -03:00
Valmo Trindade 0340a84e9c TEMP removed cfgvehicles 2025-05-22 23:22:14 -03:00
Valmo Trindade 50cf9b10bd TEMP moved CfgVehicles 2025-05-22 23:20:48 -03:00
Valmo Trindade 6e220e5807 changed release drafter cannon to prepare the release but not to do it 2025-05-22 23:14:12 -03:00
Valmo Trindade c1f61dc4aa Added initial custom marker dialog and fixed core module background 2025-05-22 23:12:36 -03:00
Valmo Trindade d8e08b8da8 removed group stuff because arma 3 code sucks 2025-05-22 23:12:17 -03:00
Valmo Trindade 1fee414ff0 added condition for adding groups into cot router 2025-05-22 03:34:11 -03:00
Valmo Trindade b41008df8b improved curator core module gui, still missing background color 2025-05-22 03:24:47 -03:00
Valmo Trindade 3d775db2cc removed core module logic after use 2025-05-22 03:24:24 -03:00
Valmo Trindade 7b5510698e refactored video streaming module 2025-05-22 03:24:10 -03:00
Valmo Trindade 3f028b48c8 Improved server module defines 2025-05-21 20:04:33 -03:00
Valmo Trindade aa7b27ac2e Added functions for adding and removing entities into the marked entitis gvar for the CoT Router 2025-05-21 20:03:59 -03:00
Valmo Trindade 2d207965db removed unused funcs 2025-05-20 21:42:15 -03:00
Valmo Trindade 2e2a321006 Added Mark Entity curator module to add entities in game 2025-05-20 21:40:27 -03:00
Valmo Trindade 67fa1cfe52 added synced units as global variables 2025-05-20 01:49:17 -03:00
Valmo Trindade 730440f4ac fixed position convert function calls 2025-05-20 01:48:55 -03:00
Valmo Trindade 1d65705aa8 Refactored server addon Cfgvehicle to allow core module to work on zeus 2025-05-19 23:35:12 -03:00
Valmo Trindade f04c0141ef Moved dialog window for TCP Socket connection startup to server addon 2025-05-19 23:34:18 -03:00
Valmo Trindade e06c199816 fixed CfgPatches modules 2025-05-19 22:54:26 -03:00
Valmo Trindade 94c7752844 Removed CfgVehicles from main addon 2025-05-19 21:58:23 -03:00
Valmo Trindade 9bdb4770c9 added notify func to cot router function 2025-05-19 21:57:32 -03:00
Valmo Trindade 98e63a7152 Rollbacked Client MEHs to the main addon to center all MEH 2025-05-18 17:58:25 -03:00
Valmo Trindade 3a179ea958 Fixed GVAR external calls 2025-05-17 23:24:30 -03:00
Valmo Trindade af15a44fb6 Moved Server and video info from main to its own addons 2025-05-17 23:15:02 -03:00
Valmo Trindade ac18c45bef Added MEH for EUD connection to set vars on players 2025-05-17 22:11:05 -03:00
Valmo Trindade 65b8aaebe3 removed video function from main 2025-05-17 22:10:47 -03:00
Valmo Trindade b3bd58385e Created video addon 2025-05-17 22:10:28 -03:00
Valmo Trindade 29574bc36c Improved callback for EUD connections in websocket 2025-05-17 05:26:36 -03:00
Valmo Trindade 6208286294 linted callback EH logging 2025-05-17 05:02:39 -03:00
Valmo Trindade 2299a3f5c9 linted video streaming callbacks 2025-05-17 05:01:50 -03:00
Valmo Trindade 098de89d95 linted TCP Socket callbacks 2025-05-17 05:01:40 -03:00
Valmo Trindade 8f7d5425ad linted all websocket callbacks 2025-05-17 04:47:01 -03:00
Valmo Trindade 938f0bcb6a Fixed postInit EH classnames 2025-05-17 04:07:03 -03:00
Valmo Trindade 577125120d Added systemChat for unhandled notify calls 2025-05-16 03:35:08 -03:00
Valmo Trindade 5c599877ca Removed callback handler, added XEH stuff to main addon 2025-05-16 03:34:51 -03:00
Valmo Trindade c1b00cb050 Switched WebSocket start motor to allow callbacks when client connects 2025-05-16 03:33:08 -03:00
Valmo Trindade 319ea9b32a added XEH_postInit to start websocket on client side 2025-05-16 01:11:22 -03:00
Valmo Trindade eda786931d added initial version of server addon to handle TCP socket into the TAK Server 2025-05-16 00:38:42 -03:00
Valmo Trindade 31f7b5178e changed main addon prefix 2025-05-16 00:25:35 -03:00
Valmo Trindade 8a6dcff05d added notify function for DRY 2025-05-16 00:25:24 -03:00
Valmo Trindade f2fe8b586c added documentation for convertClientLocation function 2025-05-16 00:23:34 -03:00
Valmo Trindade bcefc7670f removed padding on websocket router 2025-05-15 23:56:52 -03:00
Valmo Trindade 12c8781236 removed padding on macro call during socketrouter var handling 2025-05-15 23:56:35 -03:00
Valmo Trindade d81c8fa67b fixed convert location xeh call 2025-05-15 23:56:02 -03:00
Valmo Trindade 6de6a29a09 Added whole websocket handling to the client addon 2025-05-15 23:48:14 -03:00
Valmo Trindade ffcd4feb4e exploded main addon to divide componenets into addons for each feature 2025-05-15 17:53:25 -03:00
Valmo Trindade 39f4936bf7 added defines for main addon 2025-05-14 05:07:45 -03:00
Valmo Trindade 25549cda25 Added initial zeus core config module function 2025-05-14 05:07:29 -03:00
Valmo Trindade 5231dae17a added CfgMods to main config 2025-05-14 05:07:05 -03:00
Valmo Trindade f669cc1cc0 added CBA and ACE Macros for better coding xp 2025-05-13 22:36:20 -03:00
Valmo Trindade 43f1cd3bb2 added JSRS to launch mods for cool shootings 2025-05-13 01:11:13 -03:00
Valmo Trindade ec9d3693bf added initial GUI interface for zeus core module config window 2025-05-13 01:10:56 -03:00
Valmo Trindade 01efe4e01d removed private identifier from global variables 2025-05-13 01:09:51 -03:00
Valmo Trindade a997c54170 added initial zeus core module functions 2025-05-13 01:09:12 -03:00
Valmo Trindade 68b0fd1e38 added handleCallbacks function for DRY 2025-05-13 01:08:58 -03:00
Valmo Trindade 9c82832a54 updated callsign function calls i cot router loop 2025-05-10 06:18:48 -03:00
Valmo Trindade d9e7dfe497 changed extract role to handle attribute provided 2025-05-10 05:51:06 -03:00
Valmo Trindade 49afb54b80 removed old callsign function 2025-05-10 05:39:30 -03:00
Valmo Trindade 5d6846c5fa dismantled callsign function from units and markers 2025-05-10 05:38:53 -03:00
Valmo Trindade 9bb4a8feaa added 3den attributes for callsign, group color, roles, and marker types 2025-05-10 05:23:28 -03:00
Valmo Trindade 50b118cbfe called 3den config on main addon config 2025-05-09 18:46:51 -03:00
Valmo Trindade d11050fcc8 added initial Cfg3den config with callsign and role handlers 2025-05-09 18:46:36 -03:00
Valmo Trindade 3d8baae344 updated tcp scoket handler on SQF functions 2025-05-09 18:29:17 -03:00
Valmo Trindade 1d7cce8409 added stop tcp socket function to check gvars and sto the socket 2025-05-09 18:27:12 -03:00
Valmo Trindade 3f4535cf17 switched cot router anme to tcp socket on extension caller 2025-05-09 18:26:51 -03:00
Valmo Trindade 4412b67d63 updated send_human_cot to send-eud_cot to match new cot generation flow 2025-04-17 06:37:50 -03:00
Valmo Trindade 3128ac0022 Improved code structure on Cursor Over Time generation 2025-04-17 06:37:29 -03:00
Valmo Trindade b230515675 moved rust util functions to use folder structure 2025-04-16 16:51:21 -03:00
Valmo Trindade ad2f529345 defined warning in armatak video callback EHs 2025-04-16 16:50:19 -03:00
Valmo Trindade 162f3c7e7a handled RTSP video stream requests without authentication 2025-04-16 05:34:27 -03:00
Valmo Trindade ca4231f669 improved video stream filepath generation 2025-04-11 02:35:16 -03:00
Valmo Trindade 8334ff4be5 added version 2025-04-10 22:15:12 -03:00
Valmo Trindade 19907184be improved precision on kunduz map 2025-04-10 19:16:49 -03:00
Valmo Trindade f2ba112ae4 linted PR template 2025-04-08 16:05:27 -03:00
Valmo Trindade b8bb01e985 improved video feed path generator to use player's name and role 2025-04-07 04:46:53 -03:00
208 changed files with 7638 additions and 5175 deletions
+2
View File
@@ -1,3 +1,5 @@
*.rs linguist-language=Rust
*.paa filter=lfs diff=lfs merge=lfs -text
*.p3d filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
+1
View File
@@ -1,4 +1,5 @@
**When merged this pull request will:**
- _Describe what this pull request will do_
- _Each change in a separate line_
+1 -32
View File
@@ -5,32 +5,6 @@ on:
branches: [ main ]
jobs:
package_application:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
lfs: true
- name: set up JDK 11
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew assembleDebug
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: simtak
path: app/build/outputs/apk/debug/app-debug.apk
if-no-files-found: error
retention-days: 1
build_extension:
strategy:
matrix:
@@ -66,7 +40,7 @@ jobs:
retention-days: 1
package:
needs: [build_extension, package_application]
needs: [build_extension]
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
@@ -88,11 +62,6 @@ jobs:
with:
name: x86_64-unknown-linux-gnu
- run: mv ./libarmatak.so ./armatak_x64.so
- name: Download Android Application Installer
uses: actions/download-artifact@v4
with:
name: simtak
- run: mv ./app-debug.apk ./simtak.apk
- name: Setup HEMTT
uses: arma-actions/hemtt@v1
- name: Build
+1 -32
View File
@@ -5,32 +5,6 @@ on:
branches: [ main ]
jobs:
package_application:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
lfs: true
- name: set up JDK 11
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew assembleDebug
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: simtak
path: app/build/outputs/apk/debug/app-debug.apk
if-no-files-found: error
retention-days: 1
build_extension:
strategy:
matrix:
@@ -66,7 +40,7 @@ jobs:
retention-days: 1
package:
needs: [build_extension, package_application]
needs: [build_extension]
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
@@ -88,11 +62,6 @@ jobs:
with:
name: x86_64-unknown-linux-gnu
- run: mv ./libarmatak.so ./armatak_x64.so
- name: Download Android Application Installer
uses: actions/download-artifact@v4
with:
name: simtak
- run: mv ./app-debug.apk ./simtak.apk
- name: Setup HEMTT
uses: arma-actions/hemtt@v1
- name: Build
+3 -33
View File
@@ -9,31 +9,6 @@ permissions:
contents: write
jobs:
package_application:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
lfs: true
- name: Set up JDK 11
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew assembleDebug
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: simtak
path: app/build/outputs/apk/debug/app-debug.apk
if-no-files-found: error
retention-days: 1
build_extension:
strategy:
matrix:
@@ -69,7 +44,7 @@ jobs:
retention-days: 1
package:
needs: [build_extension, package_application]
needs: [build_extension]
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
@@ -91,11 +66,6 @@ jobs:
with:
name: x86_64-unknown-linux-gnu
- run: mv ./libarmatak.so ./armatak_x64.so
- name: Download Android Application Installer
uses: actions/download-artifact@v4
with:
name: simtak
- run: mv ./app-debug.apk ./simtak.apk
- name: Setup HEMTT
uses: arma-actions/hemtt@v1
- name: Build
@@ -121,8 +91,8 @@ jobs:
release_name: ${{ github.ref }}
body: |
Changes in this release:
${{ env.COMMIT_MESSAGES }}
draft: false
${{ github.event.head_commit.message }}
draft: true
prerelease: false
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
+79
View File
@@ -0,0 +1,79 @@
name: Publish Production
on:
release:
types: [published]
jobs:
build_extension:
strategy:
matrix:
os_target:
- { os: "windows-latest", target: "i686-pc-windows-msvc", artifact: "armatak.dll", name: "armatak.dll" }
- { os: "windows-latest", target: "x86_64-pc-windows-msvc", artifact: "armatak.dll", name: "armatak_x64.dll" }
- { os: "ubuntu-latest", target: "x86_64-unknown-linux-gnu", artifact: "libarmatak.so", name: "armatak.so" }
runs-on: ${{ matrix.os_target.os }}
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
lfs: true
- name: Install Rust Toolchain
uses: actions-rs/toolchain@v1
with:
target: ${{ matrix.os_target.target }}
toolchain: stable
default: true
- name: Install Dependencies (Linux only)
if: matrix.os_target.os == 'ubuntu-latest'
run: sudo apt-get update && sudo apt-get install -y build-essential
- name: Cargo Build
run: cargo build --release --target ${{ matrix.os_target.target }}
- name: check stuff
run: ls target/release
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os_target.target }}
path: target/${{ matrix.os_target.target }}/release/${{ matrix.os_target.artifact }}
if-no-files-found: error
retention-days: 1
package:
needs: [build_extension]
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
lfs: true
- run: mkdir -p ./target/release
- name: Download Windows x64 Artifact
uses: actions/download-artifact@v4
with:
name: x86_64-pc-windows-msvc
- run: mv ./armatak.dll ./armatak_x64.dll
- name: Download Windows x86 Artifact
uses: actions/download-artifact@v4
with:
name: i686-pc-windows-msvc
- name: Download Linux x64 Artifact
uses: actions/download-artifact@v4
with:
name: x86_64-unknown-linux-gnu
- run: mv ./libarmatak.so ./armatak_x64.so
- name: Setup HEMTT
uses: arma-actions/hemtt@v1
- name: Build
run: hemtt release
- name: Extract Zipped Mod
run: unzip releases/armatak-latest.zip -d releases
- uses: arma-actions/workshop-upload@v1
with:
appId: '107410'
itemId: ${{ secrets.STEAM_WORKSHOP_PROD_ID }}
contentPath: releases/@armatak
changelog: 'Update'
env:
STEAM_USERNAME: ${{ secrets.STEAM_USERNAME }}
STEAM_PASSWORD: ${{ secrets.STEAM_PASSWORD }}
+1
View File
@@ -3,6 +3,7 @@
hemtt
hemtt.exe
*.biprivatekey
.hemttprivatekey
source/
.vscode
releases/
+23 -23
View File
@@ -4,10 +4,10 @@ name = "ARMA Team Awareness Kit"
prefix = "armatak"
[version]
build = 9
major = 0
minor = 9
patch = 9
build = 0
major = 1
minor = 1
patch = 0
git_hash = 0
@@ -25,8 +25,7 @@ include = [
"LICENSE",
"*.dll",
"*.so",
"*.paa",
"simtak.apk"
"*.paa"
]
[properties]
@@ -38,28 +37,29 @@ preset = "Hemtt"
[hemtt.launch.default]
workshop = [
"450814997", # CBA
"450814997", # CBA_A3
"463939057", # ACE
"623475643", # 3den enhanced
"1779063631", # Zeus enhanced
"1673595418", # User Input Menus
"1678581937", # Extended Function Viewer
"1231625987", #Debug Console
"751965892", # ACRE2
"2522638637", # ACE Extended Arsenal
"333310405", # Enhanced Movement
"2034363662", # Enhanced Movement Rework
"2941986336", # Hatchet Interaction Framework - Stable Version
"1745501605", # Hatchet H-60 pack - Stable Version
"843577117", # RHSUSAF
"843425103", # RHSAFRF
"843632231", # RHSSAF
"843593391", # RHSGREF
"735566597", # Project OPFOR
"3030830594", # Western Dusk
"3147473073", # TOTT Core
"3147480843", # TOTT CAG
"3147476552", # TOTT Optics
"2975268929", # GPNVG
"583496184", # CUP Terrains
"421620913", # Kunduz
"2397360831", # USAF Core
"2397376046", # USAF Utility
"2226368165", # USAF AC130
"1673456286", # 3CB Factions
"623475643", # 3den Enhanced
"2257686620", # Blastcore Murr Edition
"583496184", # CUP Terrains - Core
"3078351739", # Kunduz River
"1858075458", # LAMBS_Danger.fsm
"1808238502", # LAMBS_Suppression
"3425368881", # M4A1_URGI
"2268351256", # Tier One Weapons
"2560276469", # Restrict Markers
"3493557838" # Ballad of the Green Berets
]
parameters = [
Generated
+841 -1056
View File
File diff suppressed because it is too large Load Diff
+5 -12
View File
@@ -1,26 +1,19 @@
[package]
name = "armatak"
version = "0.9.9"
version = "1.0.1"
edition = "2021"
[dependencies]
arma-rs = "1.10.4"
chrono = "0.4.39"
futures = "0.3.31"
futures-util = "0.3.31"
http = "1.1.0"
lazy_static = "1.5.0"
log = "0.4.22"
log4rs = "1.3.0"
once_cell = "1.19.0"
qrcode = "0.14.1"
regex = "1.10.6"
reqwest = { version = "0.12.7", features = ["blocking"] }
reqwest = { version = "0.12.15", default-features = false, features = ["blocking", "json", "rustls-tls"] }
rcgen = { version = "0.13.2", default-features = false, features = ["crypto", "pem", "aws_lc_rs"] }
rustls = "0.23.23"
rustls-pemfile = "2.2.0"
serde = { version = "1.0.210", features = ["derive"] }
serde_json = "1.0.128"
tokio = { version = "1.40", features = ["full"] }
tokio-tungstenite = "0.24.0"
ws = "0.9.2"
[dependencies.uuid]
version = "1.10.0"
+4
View File
@@ -4,6 +4,10 @@
ARMATAK is a server side Arma 3 addons for streaming unit positions to TAK Clients in sessions on real locations maps. It can be runned both as a clientside mod or a serverside mod, when runned serverside, it will create a TCP Socket connection between Arma 3 and the TAK Server, sending the game session information into it. When used clientside, Arma 3 will host a websocket server that you can connect to your phone and mock the phone's location to the player's in game location.
The server-side CoT router supports two transports:
- Plain TCP, for legacy TAK ingress.
- Mutual TLS, using the TAK Server authentication API, so the Arma session can publish as an authenticated TAK device on port `8089`.
## Get in Touch
[Join the Discord Server for ARMATAK!](https://discord.gg/svK64PCycU)
+1
View File
@@ -0,0 +1 @@
armatak\armatak\addons\client
+17
View File
@@ -0,0 +1,17 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));
};
};
class Extended_PreInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preInit));
};
};
class Extended_PostInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_postInit));
};
};
+3
View File
@@ -0,0 +1,3 @@
PREP(convertClientLocation);
PREP(extractClientPosition);
PREP(startUDPSocket);
+8
View File
@@ -0,0 +1,8 @@
#include "script_component.hpp"
if (!hasInterface) exitWith {};
_local_address = "armatak" callExtension ["local_ip", []] select 0;
SETVAR(player,GVAR(localAddress),_local_address);
SETVAR(player,GVAR(eudConnected),false);
+9
View File
@@ -0,0 +1,9 @@
#include "script_component.hpp"
ADDON = false;
PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
ADDON = true;
+3
View File
@@ -0,0 +1,3 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"
+35
View File
@@ -0,0 +1,35 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredAddons[] = {
"cba_main",
"ace_main",
"armatak_main"
};
requiredVersion = REQUIRED_VERSION;
author = PROJECT_AUTHOR;
url = "https://github.com/valmojr/armatak";
};
};
class CfgVehicles {
class Man;
class CAManBase: Man {
class ACE_SelfActions {
class danceParty {
displayName = "Connect to EUD";
condition = "!(player getVariable ['armatak_client_eudConnected', false])";
exceptions[] = {};
statement = "createDialog 'armatak_udp_socket_start_dialog'";
icon = "";
};
};
};
};
#include "CfgEventHandlers.hpp"
#include "dialog.hpp"
+73
View File
@@ -0,0 +1,73 @@
class RscText;
class RscBackground;
class RscButton;
class RscEdit;
class armatak_udp_socket_start_dialog {
idd = 999091;
movingEnable = 0;
class ControlsBackground {
class armatak_gui_module_udp_socket_dialog_main_frame: RscBackground {
idc = 16960;
x = "0.386562 * safezoneW + safezoneX";
y = "0.401 * safezoneH + safezoneY";
w = "0.216563 * safezoneW";
h = "0.242 * safezoneH";
colorBackground[]={0,0,0,0.45};
};
};
class Controls {
class armatak_gui_module_udp_socket_dialog_address_edit: RscEdit {
idc = 16961;
text = "168.15.0.3";
x = "0.391719 * safezoneW + safezoneX";
y = "0.445 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.044 * safezoneH";
colorBackground[]={0,0,0,0.5};
};
class armatak_gui_module_udp_socket_dialog_address_port_edit: RscEdit {
idc = 16962;
text = "4349";
x = "0.391719 * safezoneW + safezoneX";
y = "0.522 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.044 * safezoneH";
colorBackground[]={0,0,0,0.5};
};
class armatak_gui_module_udp_socket_dialog_address_text: RscText {
idc = 16963;
text = "Phone's Socket Local Address";
x = "0.391719 * safezoneW + safezoneX";
y = "0.412 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.033 * safezoneH";
};
class armatak_gui_module_udp_socket_dialog_address_port_text: RscText {
idc = 16964;
text = "Phone's Socket Local Port";
x = "0.391719 * safezoneW + safezoneX";
y = "0.489 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.033 * safezoneH";
};
class armatak_gui_module_udp_socket_dialog_address_button_cancel: RscButton {
idc = 16965;
text = "Cancel";
action = "closeDialog 2;";
x = "0.551563 * safezoneW + safezoneX";
y = "0.577 * safezoneH + safezoneY";
w = "0.0464063 * safezoneW";
h = "0.055 * safezoneH";
};
class armatak_gui_module_udp_socket_dialog_address_button_ok: RscButton {
idc = 16966;
text = "Ok";
action = QUOTE(call FUNC(startUDPSocket));
x = "0.5 * safezoneW + safezoneX";
y = "0.577 * safezoneH + safezoneY";
w = "0.0464063 * safezoneW";
h = "0.055 * safezoneH";
};
};
};
@@ -0,0 +1,124 @@
#include "..\script_component.hpp"
/*
* Author: Valmo Trindade
* This function is used to convert the position of a unit to the world world location.
*
* Argument:
* 0: in game latitude <NUMBER> is the latitude of the unit.
* 1: in game longitude <NUMBER> is the longitude of the unit.
* 2: in game altitude <NUMBER> is the altitude of the unit.
* 3: in game bearing <NUMBER> is the bearing of the unit.
*
* Return Value:
* ARRAY -> [latitude, longitude, altitude, bearing]
*
* Example:
* [player] call armatak_client_fnc_convertClientLocation;
*
* Public: Yes
*/
params["_latitude", "_longitude", "_altitude"];
_position = [_latitude, _longitude, _altitude];
_realLocation = null;
switch (toLower worldName) do {
case "altis": {
_realLocation = _position call armatak_fnc_convert_to_altis;
};
case "stratis": {
_realLocation = _position call armatak_fnc_convert_to_stratis;
};
case "malden": {
_realLocation = _position call armatak_fnc_convert_to_malden;
};
case "vr": {
_realLocation = _position call armatak_fnc_convert_to_vr;
};
case "lawn": {
_realLocation = _position call armatak_fnc_convert_to_lawn;
};
case "cucui": {
_realLocation = _position call armatak_fnc_convert_to_cucui;
};
case "chernarus": {
_realLocation = _position call armatak_fnc_convert_to_chernarus;
};
case "chernarus_summer": {
_realLocation = _position call armatak_fnc_convert_to_chernarus;
};
case "chernarus_winter": {
_realLocation = _position call armatak_fnc_convert_to_chernarus;
};
case "bootcamp_acr": {
_realLocation = _position call armatak_fnc_convert_to_bukovina;
};
case "woodland_acr": {
_realLocation = _position call armatak_fnc_convert_to_bystrika;
};
case "mountains_acr": {
_realLocation = _position call armatak_fnc_convert_to_takistan_montains;
};
case "sara_dbe1": {
_realLocation = _position call armatak_fnc_convert_to_united_sahrani;
};
case "saralite": {
_realLocation = _position call armatak_fnc_convert_to_southen_sahrani;
};
case "enoch": {
_realLocation = _position call armatak_fnc_convert_to_livonia;
};
case "kunduz": {
_realLocation = _position call armatak_fnc_convert_to_kunduz;
};
case "kunduz_valley": {
_realLocation = _position call armatak_fnc_convert_to_kunduz_valley;
};
case "malvinasfalkands": {
_realLocation = _position call armatak_fnc_convert_to_malvinas_malvinasfalkands;
};
case "pebble_island_airfield": {
_realLocation = _position call armatak_fnc_convert_to_malvinas_pebble_island_airfield;
};
case "p_argentino_stanley": {
_realLocation = _position call armatak_fnc_convert_to_malvinas_p_argentino_stanley;
};
case "top_malo_house": {
_realLocation = _position call armatak_fnc_convert_to_malvinas_top_malo_house;
};
case "pradera_ganso": {
_realLocation = _position call armatak_fnc_convert_to_malvinas_pradera_ganso;
};
case "tanoa": {
_realLocation = _position call armatak_fnc_convert_to_tanoa;
};
case "zagor_zagorsk_reserved_forest": {
_realLocation = _position call armatak_fnc_convert_to_zagor_zagorsk_reserved_forest;
};
case "umb_colombia": {
_realLocation = _position call armatak_fnc_convert_to_colombia;
};
case "clafghan": {
_realLocation = _position call armatak_fnc_convert_to_clafghan;
};
case "rut_mandol": {
_realLocation = _position call armatak_fnc_convert_to_rut_mandol;
};
case "hellanmaa": {
_realLocation = _position call armatak_fnc_convert_to_hellanmaa;
};
case "hellanmaaw": {
_realLocation = _position call armatak_fnc_convert_to_hellanmaa;
};
default {
_warning = format ["<t color='#FF8021'>ARMATAK</t><br/> %1", "Unsupported Map"];
[[_warning, 1.5]] call CBA_fnc_notify;
_realLocation = [0, 0, 0];
};
};
_realLocation
@@ -0,0 +1,29 @@
#include "..\script_component.hpp"
/*
* Author: Valmo Trindade
* This function is used to extract the position of a unit and convert it to a format suitable for SIMTAK.
*
* Argument:
* 0: The first argument <OBJECT> is the unit whose position you want to extract.
*
* Return Value:
* ARRAY -> [latitude, longitude, altitude, bearing]
*
* Example:
* [player] call armatak_client_fnc_extractClientPosition;
*
* Public: Yes
*/
params["_unit"];
private _uuid = _unit call armatak_fnc_extract_uuid;
private _pos = (getPos _unit) call FUNC(convertClientLocation);
private _callsign = _unit call armatak_fnc_extract_unit_callsign;
private _bearing = parseNumber ((getDir _unit) toFixed 0);
private _speed = speed _unit / 3.6;
_payload = [_uuid, _pos select 0, _pos select 1, _pos select 2, _callsign, _bearing, _speed, _callsign];
_payload
@@ -0,0 +1,31 @@
#include "..\script_component.hpp"
params ["_logic"];
_socket_is_running = player getVariable [QGVAR(eudConnected), false];
if (_socket_is_running) exitWith {
["Socket is already running", "error", "UDP Socket"] call EFUNC(main,notify);
closeDialog 1;
};
disableSerialization;
_udp_socket_instance_address = ctrlText 16961;
_udp_socket_instance_port = ctrlText 16962;
_udp_socket_fulladdress = ((_udp_socket_instance_address) + ":" + (_udp_socket_instance_port));
player setVariable [QGVAR(udp_socket_address), _udp_socket_fulladdress];
player setVariable [QGVAR(eudConnected), true];
"armatak" callExtension ["udp_socket:start", [_udp_socket_fulladdress]];
[{
if (player getVariable [QGVAR(eudConnected), false]) then {
"armatak" callExtension ["udp_socket:send_gps_cot", [player call FUNC(extractClientPosition)]];
};
}, 0.5, []] call CBA_fnc_addPerFrameHandler;
deleteVehicle _logic;
closeDialog 1;
+17
View File
@@ -0,0 +1,17 @@
#define COMPONENT client
#define COMPONENT_BEAUTIFIED WebSocket Client
#include "\armatak\armatak\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS
#ifdef DEBUG_ENABLED_CLIENT
#define DEBUG_MODE_FULL
#endif
#ifdef DEBUG_SETTINGS_CLIENT
#define DEBUG_SETTINGS DEBUG_SETTINGS_CLIENT
#endif
#include "\z\ace\addons\main\script_macros.hpp"
+1 -1
View File
@@ -1 +1 @@
armatak\armatak\armatak_main
armatak\armatak\addons\main
+170
View File
@@ -0,0 +1,170 @@
class Cfg3den {
class Object {
class AttributeCategories {
class armatak_3den_attributes {
displayName = "ARMA Team Awareness Kit";
class Attributes {
class armatak_attribute_unit_callsign {
displayName = "Unit Callsign";
tooltip = "Unit callsign on TAK";
property = "armatak_attribute_unit_callsign";
control = "Edit";
expression = "_this setVariable ['armatak_attribute_unit_callsign',_value]";
defaultValue = "''";
condition = "objectBrain";
typeName = "STRING";
};
class armatak_attribute_unit_role {
displayName = "Unit Role";
tooltip = "Unit role on TAK";
property = "armatak_attribute_unit_role";
control = "Combo";
class Values {
class armatak_attribute_unit_role_value_teammember {
name = "Team Member";
value = "Team Member";
default = 1;
};
class armatak_attribute_unit_role_value_teamleader {
name = "Team Leader";
value = "Team Lead";
};
class armatak_attribute_unit_role_value_hq {
name = "Headquarters";
value = "HQ";
};
class armatak_attribute_unit_role_value_sniper {
name = "Sniper";
value = "Sniper";
};
class armatak_attribute_unit_role_value_medic {
name = "Medic";
value = "Medic";
};
class armatak_attribute_unit_role_value_forward_observer {
name = "Forward Observer";
value = "Forward Observer";
};
class armatak_attribute_unit_role_value_rto {
name = "Radio Telephone Operator";
value = "RTO";
};
class armatak_attribute_unit_role_value_k9 {
name = "K9 Operator";
value = "K9";
};
};
expression = "_this setVariable ['%s',_value];";
unique = 0;
condition = "objectBrain";
};
class armatak_attribute_marker_callsign {
displayName = "Marker Callsign";
tooltip = "Marker Callsign on TAK";
property = "armatak_attribute_marker_callsign";
control = "Edit";
expression = "_this setVariable ['armatak_attribute_marker_callsign',_value]";
defaultValue = "''";
condition = "objectVehicle";
typeName = "STRING";
};
class armatak_attribute_marker_type {
displayName = "Marker Type";
tooltip = "Marker type on TAK";
property = "armatak_attribute_marker_type";
control = "Edit";
expression = "_this setVariable ['armatak_attribute_marker_type',_value]";
defaultValue = "''";
condition = "objectVehicle";
typeName = "STRING";
};
class armatak_attribute_video_url {
displayName = "Video URL (RTSP)";
tooltip = "RTSP stream URL for UAS Tool integration. When set, the drone will appear in the ATAK UAS Tool with FOV cone and video feed. Format: rtsp://address:port/path (e.g. rtsp://192.168.1.10:8554/live/drone1). Leave empty to disable UAS Tool integration for this entity.";
property = "armatak_attribute_video_url";
control = "Edit";
expression = "_this setVariable ['armatak_attribute_video_url',_value]";
defaultValue = "''";
condition = "objectVehicle";
typeName = "STRING";
};
};
};
};
};
class Group {
class AttributeCategories {
class armatak_3den_group_attributes {
displayName = "ARMA Team Awareness Kit";
class Attributes {
class armatak_attribute_group_color {
displayName = "Color";
tooltip = "Group on TAK";
property = "armatak_attribute_group_color";
control = "Combo";
class Values {
class armatak_attribute_group_color_value_white {
name = "White";
value = "White";
};
class armatak_attribute_group_color_value_yellow {
name = "Yellow";
value = "Yellow";
};
class armatak_attribute_group_color_value_orange {
name = "Orange";
value = "Orange";
};
class armatak_attribute_group_color_value_magenta {
name = "Magenta";
value = "Magenta";
};
class armatak_attribute_group_color_value_red {
name = "Red";
value = "Red";
};
class armatak_attribute_group_color_value_maroon {
name = "Maroon";
value = "Maroon";
};
class armatak_attribute_group_color_value_purple {
name = "Purple";
value = "Purple";
};
class armatak_attribute_group_color_value_darkblue {
name = "Dark Blue";
value = "DarkBlue";
};
class armatak_attribute_group_color_value_blue {
name = "Blue";
value = "Blue";
};
class armatak_attribute_group_color_value_cyan {
name = "Cyan";
value = "Cyan";
};
class armatak_attribute_group_color_value_teal {
name = "Teal";
value = "Teal";
};
class armatak_attribute_group_color_value_green {
name = "Green";
value = "Green";
};
class armatak_attribute_group_color_value_darkgreen {
name = "Dark Green";
value = "DarkGreen";
};
class armatak_attribute_group_color_value_brown {
name = "Brown";
value = "Brown";
};
};
expression = "_this setVariable ['%s',_value];";
unique = 0;
};
};
};
};
};
};
+17
View File
@@ -0,0 +1,17 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));
};
};
class Extended_PreInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preInit));
};
};
class Extended_PostInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_postInit));
};
};
+76 -43
View File
@@ -1,99 +1,132 @@
class CfgFunctions {
class armatak {
class functions {
class init {
file = "\armatak\armatak\armatak_main\functions\fn_init.sqf";
};
class video_init {
file = "\armatak\armatak\armatak_main\functions\fn_video_init.sqf";
};
class log_message {
file = "\armatak\armatak\armatak_main\functions\fn_log_message.sqf";
};
class send_digital_pointer_cot {
file = "\armatak\armatak\armatak_main\functions\api\fn_send_digital_pointer_cot.sqf";
file = "\armatak\armatak\addons\main\functions\api\fn_send_digital_pointer_cot.sqf";
};
class send_drone_cot {
file = "\armatak\armatak\armatak_main\functions\api\fn_send_drone_cot.sqf";
file = "\armatak\armatak\addons\main\functions\api\fn_send_drone_cot.sqf";
};
class send_group_cots {
file = "\armatak\armatak\armatak_main\functions\api\fn_send_group_cots.sqf";
file = "\armatak\armatak\addons\main\functions\api\fn_send_group_cots.sqf";
};
class send_human_cot {
file = "\armatak\armatak\armatak_main\functions\api\fn_send_human_cot.sqf";
class send_enemy_cot {
file = "\armatak\armatak\addons\main\functions\api\fn_send_enemy_cot.sqf";
};
class send_eud_cot {
file = "\armatak\armatak\addons\main\functions\api\fn_send_eud_cot.sqf";
};
class send_marker_cot {
file = "\armatak\armatak\armatak_main\functions\api\fn_send_marker_cot.sqf";
file = "\armatak\armatak\addons\main\functions\api\fn_send_marker_cot.sqf";
};
class send_message_cot {
file = "\armatak\armatak\armatak_main\functions\api\fn_send_marker_cot.sqf";
class send_uas_video_cot {
file = "\armatak\armatak\addons\main\functions\api\fn_send_uas_video_cot.sqf";
};
class extract_callsign {
file = "\armatak\armatak\armatak_main\functions\extract_data\fn_extract_callsign.sqf";
class send_uas_sensor_cot {
file = "\armatak\armatak\addons\main\functions\api\fn_send_uas_sensor_cot.sqf";
};
class stop_tcp_socket {
file = "\armatak\armatak\addons\main\functions\api\fn_stop_tcp_socket.sqf";
};
class extract_group_color {
file = "\armatak\armatak\armatak_main\functions\extract_data\fn_extract_group_color.sqf";
file = "\armatak\armatak\addons\main\functions\extract_data\fn_extract_group_color.sqf";
};
class extract_group_role {
file = "\armatak\armatak\armatak_main\functions\extract_data\fn_extract_group_role.sqf";
file = "\armatak\armatak\addons\main\functions\extract_data\fn_extract_group_role.sqf";
};
class extract_marker_callsign {
file = "\armatak\armatak\addons\main\functions\extract_data\fn_extract_marker_callsign.sqf";
};
class extract_role {
file = "\armatak\armatak\armatak_main\functions\extract_data\fn_extract_role.sqf";
file = "\armatak\armatak\addons\main\functions\extract_data\fn_extract_role.sqf";
};
class extract_position {
file = "\armatak\armatak\armatak_main\functions\extract_data\fn_extract_position.sqf";
class extract_sensor_data {
file = "\armatak\armatak\addons\main\functions\extract_data\fn_extract_sensor_data.sqf";
};
class extract_unit_callsign {
file = "\armatak\armatak\addons\main\functions\extract_data\fn_extract_unit_callsign.sqf";
};
class extract_uuid {
file = "\armatak\armatak\armatak_main\functions\extract_data\fn_extract_uuid.sqf";
file = "\armatak\armatak\addons\main\functions\extract_data\fn_extract_uuid.sqf";
};
class shorten_name {
file = "\armatak\armatak\armatak_main\functions\extract_data\fn_shorten_name.sqf";
file = "\armatak\armatak\addons\main\functions\extract_data\fn_shorten_name.sqf";
};
class convert_location {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_location.sqf";
};
class convert_to_altis {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_altis.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_altis.sqf";
};
class convert_to_bukovina {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_bukovina.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_bukovina.sqf";
};
class convert_to_bystrika {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_bystrika.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_bystrika.sqf";
};
class convert_to_chernarus {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_chernarus.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_chernarus.sqf";
};
class convert_to_cucui {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_cucui.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_cucui.sqf";
};
class convert_to_kunduz {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_kunduz.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_kunduz.sqf";
};
class convert_to_kunduz_valley {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_kunduz_valley.sqf";
};
class convert_to_lawn {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_lawn.sqf";
};
class convert_to_livonia {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_livonia.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_livonia.sqf";
};
class convert_to_malden {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_malden.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_malden.sqf";
};
class convert_to_malvinas_malvinasfalkands {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_malvinas_malvinasfalkands.sqf";
};
class convert_to_malvinas_p_argentino_stanley {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_malvinas_p_argentino_stanley.sqf";
};
class convert_to_malvinas_pebble_island_airfield {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_malvinas_pebble_island_airfield.sqf";
};
class convert_to_malvinas_pradera_ganso {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_malvinas_pradera_ganso.sqf";
};
class convert_to_malvinas_top_malo_house {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_malvinas_top_malo_house.sqf";
};
class convert_to_southen_sahrani {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_southen_sahrani.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_southen_sahrani.sqf";
};
class convert_to_stratis {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_stratis.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_stratis.sqf";
};
class convert_to_takistan_montains {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_takistan_montains.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_takistan_montains.sqf";
};
class convert_to_tanoa {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_tanoa.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_tanoa.sqf";
};
class convert_to_united_sahrani {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_united_sahrani.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_united_sahrani.sqf";
};
class convert_to_vr {
file = "\armatak\armatak\armatak_main\functions\map\fn_convert_to_vr.sqf";
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_vr.sqf";
};
class convert_to_zagor_zagorsk_reserved_forest {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_zagor_zagorsk_reserved_forest.sqf";
};
class convert_to_colombia {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_colombia.sqf";
};
class convert_to_clafghan {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_clafghan.sqf";
};
class convert_to_rut_mandol {
file = "\armatak\armatak\addons\main\functions\map\fn_convert_to_rut_mandol.sqf";
};
};
};
-172
View File
@@ -1,172 +0,0 @@
class CfgFactionClasses {
class NO_CATEGORY;
class armatak_module_category: NO_CATEGORY {
displayName = "Team Awareness Kit";
};
};
class CfgVehicles {
class Logic;
class Module_F : Logic
{
class AttributesBase
{
class Default;
class Edit; // Default edit box (i.e. text input field)
class Combo; // Default combo box (i.e. drop-down menu)
class Checkbox; // Default checkbox (returned value is Boolean)
class CheckboxNumber; // Default checkbox (returned value is Number)
class ModuleDescription; // Module description
class Units; // Selection of units on which the module is applied
};
class ModuleDescription
{
class AnyBrain;
};
};
class armatak_module_core: Module_F {
scope = 2;
displayname = "ARMATAK CoT Router";
icon = "\a3\Modules_F_Curator\Data\iconRadio_ca.paa";
category = "armatak_module_category";
function = "armatak_fnc_init";
functionPriority = 1;
isGlobal = 0;
isTriggerActivated = 0;
isDisposable = 1;
is3den = 0;
curatorCanAttach = 0;
curatorInfoType = "RscDisplayAttributeModuleNuke";
canSetArea = 0;
canSetAreaShape = 0;
canSetAreaHeight = 0;
class AttributesValues {
size3[] = { 1, 1, -1 };
isRectangle = 0;
};
class Attributes: AttributesBase {
class armatak_module_tak_server_instance_address: Edit {
property = "armatak_module_tak_server_instance_address";
displayname = "TAK Server Address";
tooltip = "TAK Server Instance Address";
typeName = "STRING";
defaultValue = "localhost";
};
class armatak_module_tak_server_instance_port: Edit {
property = "armatak_module_tak_server_instance_port";
displayname = "TAK Server TCP Port";
tooltip = "TAK Server instance Port for TCP connection";
typeName = "NUMBER";
defaultValue = "8088";
};
class ModuleDescription: ModuleDescription {};
};
class ModuleDescription: ModuleDescription {
description = "Generate the initial ARMATAK configuration, syncronizing all players to the TAK server instance";
sync[] = {"LocationArea_F"};
class LocationArea_F {
description[] = {
"First line",
"Second line"
};
position = 1;
direction = 1;
optional = 1;
duplicate = 1;
synced[] = { "BluforUnit", "AnyBrain" };
};
class BluforUnit
{
description = "Short description";
displayName = "Any BLUFOR unit";
icon = "iconMan";
side = 1;
};
};
};
class armatak_module_video_stream_core: armatak_module_core {
scope = 2;
displayname = "ARMATAK MediaMTX Video Feed Parser";
icon = "\a3\Modules_F_Curator\Data\iconcuratorsetcamera_ca.paa";
category = "armatak_module_category";
function = "armatak_fnc_video_init";
functionPriority = 1;
isGlobal = 0;
isTriggerActivated = 0;
isDisposable = 1;
is3den = 0;
curatorCanAttach = 0;
curatorInfoType = "RscDisplayAttributeModuleNuke";
canSetArea = 0;
canSetAreaShape = 0;
canSetAreaHeight = 0;
class AttributesValues {
size3[] = { 1, 1, -1 };
isRectangle = 0;
};
class Attributes: AttributesBase {
class armatak_module_mediamtx_video_stream_instance_address: Edit {
property = "armatak_module_mediamtx_video_stream_instance_address";
displayname = "MediaMTX Provider Address";
tooltip = "MediaMTX Provider Instance Address";
typeName = "STRING";
defaultValue = "localhost";
};
class armatak_module_mediamtx_video_stream_instance_port: Edit {
property = "armatak_module_mediamtx_video_stream_instance_port";
displayname = "MediaMTX Provider Port";
tooltip = "MediaMTX Provider Port for handling video streams";
typeName = "STRING";
defaultValue = "8554";
};
class armatak_module_mediamtx_video_stream_instance_auth_user: Edit {
property = "armatak_module_mediamtx_video_stream_instance_auth_user";
displayname = "MediaMTX Provider Username";
tooltip = "MediaMTX Provider Instance Username";
typeName = "STRING";
defaultValue = "administrator";
};
class armatak_module_mediamtx_video_stream_instance_auth_pass: Edit {
property = "armatak_module_mediamtx_video_stream_instance_auth_pass";
displayname = "MediaMTX Provider Password";
tooltip = "MediaMTX Provider Instance Password";
typeName = "STRING";
defaultValue = "password";
};
class ModuleDescription: ModuleDescription {};
};
class ModuleDescription: ModuleDescription {
description = "Generate the initial ARMATAK configuration, syncronizing all players to the TAK server instance";
sync[] = {"LocationArea_F"};
class LocationArea_F {
description[] = {
"First line",
"Second line"
};
position = 1;
direction = 1;
optional = 1;
duplicate = 1;
synced[] = { "BluforUnit", "AnyBrain" };
};
class BluforUnit
{
description = "Short description";
displayName = "Any BLUFOR unit";
icon = "iconMan";
side = 1;
};
};
};
};
+2
View File
@@ -0,0 +1,2 @@
PREP(logMessage);
PREP(notify);
+61
View File
@@ -0,0 +1,61 @@
#include "script_component.hpp"
addMissionEventHandler ["ExtensionCallback", {
params ["_name", "_function", "_data"];
switch (_name) do {
case "UDP SOCKET": {
[_function, "success", _name] call FUNC(notify);
switch (_function) do {
case "EUD Connected": {
SETVAR(player,EGVAR(client,eudConnected),true);
};
case "EUD Disconnected": {
SETVAR(player,EGVAR(client,eudConnected),false);
};
default {};
};
};
case "UDP SOCKET WARNING": {
[_function, "warning", "UDP Socket"] call FUNC(notify);
};
case "UDP SOCKET ERROR": {
[_function, "error", _name] call FUNC(notify);
if (_function == "UDP Socket is not running") then {
SETVAR(player,EGVAR(client,eudConnected),false);
};
if (_function == "failed to bind UDP socket") then {
SETVAR(player,EGVAR(client,eudConnected),false);
};
};
case "TCP SOCKET": {
[_function, "success", _name] call FUNC(notify);
};
case "TCP SOCKET ERROR": {
_message = _function;
if (_data isNotEqualTo "") then {
_message = format ["%1: %2", _function, _data];
};
[_message, "error", _name] call FUNC(notify);
};
case "VIDEO": {
[_function, "success", _name] call FUNC(notify);
};
case "VIDEO ERROR": {
[_function, "error", _name] call FUNC(notify);
SETVAR(player,EGVAR(video,isStreaming),false);
};
default {
"armatak" callExtension ["log",["error", (_name + _function + _data)]];
};
};
}];
GVAR(group_colors) = ["White", "Yellow", "Orange", "Magenta", "Red", "Maroon", "Purple", "DarkBlue", "Blue", "Cyan", "Teal", "Green", "DarkGreen", "Brown"];
missionNamespace setVariable [QGVAR(group_colors), GVAR(group_colors)];
+9
View File
@@ -0,0 +1,9 @@
#include "script_component.hpp"
ADDON = false;
PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
ADDON = true;
+3
View File
@@ -0,0 +1,3 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"
+35 -15
View File
@@ -1,26 +1,46 @@
#include "script_component.hpp"
class CfgPatches {
class armatak_main {
units[] = {
"armatak_module_core",
"armatak_module_callsign"
};
weapons[] = {""};
author = "Valmo";
url = "https://github.com/valmojr/armatak";
requiredAddons[] =
{
class ADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredAddons[] = {
"cba_main",
"ace_main"
};
requiredVersion = 2.06;
requiredVersion = REQUIRED_VERSION;
author = PROJECT_AUTHOR;
url = "https://github.com/valmojr/armatak";
};
};
class Extended_PostInit_EventHandlers {
class armatak_main {
init = "call compileScript ['\armatak\armatak\armatak_main\initPlayerLocal.sqf']";
class CfgMods {
class PREFIX {
name = "Arma Team Awareness Kit";
author = PROJECT_AUTHOR;
logo = "logo_ca.paa";
logoOver = "logo_hover_ca.paa";
tooltip = "ARMATAK";
tooltipOwned = "ARMATAK";
picture = "picture.paa";
actionName = "GitHub";
action = "https://github.com/valmojr/armatak";
overview = "ARMATAK Addons allows Arma 3 sessions to be parsed to TAK Clients";
hideName = 0;
hidePicture = 0;
dlcColor[] = { 0.23, 0.39, 0.30, 1 };
logoSmall = "logo_small_ca.paa";
};
};
class CfgFactionClasses {
class NO_CATEGORY;
class GVAR(moduleCategory): NO_CATEGORY {
displayName = "Team Awareness Kit";
};
};
#include "CfgEventHandlers.hpp"
#include "CfgFunctions.hpp"
#include "CfgVehicles.hpp"
#include "Cfg3den.hpp"
@@ -3,12 +3,12 @@ params ["_unit"];
_digitalPointer = laserTarget _unit;
if (!isNull _digitalPointer) then {
_digitalPointerPosition = _digitalPointer call armatak_fnc_extract_position;
_digitalPointerPosition = _digitalPointer call armatak_client_fnc_extractClientPosition;
_link_uid = [_unit] call armatak_fnc_extract_uuid;
_contact_callsign = ([player] call armatak_fnc_extract_callsign) + ".DP1";
_contact_callsign = ([player] call armatak_fnc_extract_unit_callsign) + ".DP1";
_dpCot = [_link_uid, _contact_callsign, _digitalPointerPosition select 0, _digitalPointerPosition select 1, _digitalPointerPosition select 2];
_dpCot = [_link_uid, _contact_callsign, _digitalPointerPosition select 1, _digitalPointerPosition select 2, _digitalPointerPosition select 3];
"armatak" callExtension ["cot_router:send_digital_pointer_cot", [_dpCot]];
"armatak" callExtension ["tcp_socket:cot:digital_pointer", [_dpCot]];
};
@@ -1,11 +1,11 @@
// function name: armatak_fnc_extract_drone
// function name: armatak_fnc_send_drone_cot
// function author: Valmo
// function description: Gets the drone information for the CoT Router
params["_drone"];
private _atak_role = "a-f-A";
private _atak_callsign = [_unit] call armatak_fnc_extract_callsign;
private _atak_callsign = [_drone] call armatak_fnc_extract_marker_callsign;
switch (side _drone) do {
case "WEST": {
@@ -25,4 +25,13 @@ switch (side _drone) do {
};
};
_pre_defined_role = _drone getVariable "_atak_group_role";
if (!isNil "_pre_defined_role") then {
_callsign = _pre_defined_role;
};
_cot = [_drone, _atak_role, _atak_callsign] call armatak_fnc_send_marker_cot;
[_drone] call armatak_fnc_send_uas_video_cot;
[_drone] call armatak_fnc_send_uas_sensor_cot;
@@ -0,0 +1,15 @@
// function name: armatak_fnc_send_eud_cot
// function author: Valmo
// function description: Gets the information necessary for generating the EUD Cursor Over Time
params ["_unit"];
_unit_position = _unit call armatak_client_fnc_extractClientPosition;
_uuid = _unit call armatak_fnc_extract_uuid;
_type = _unit call armatak_fnc_extract_role;
_callsign = _unit call armatak_fnc_extract_marker_callsign;
_marker_cot = [_uuid, _type, _unit_position select 1, _unit_position select 2, _unit_position select 3, _callsign, _unit_position select 5, _unit_position select 6];
"armatak" callExtension ["tcp_socket:cot:marker", [_marker_cot]];
@@ -0,0 +1,12 @@
// function name: armatak_fnc_send_eud_cot
// function author: Valmo
// function description: Gets the information necessary for generating the EUD Cursor Over Time
params ["_unit", "_callsign", "_group_name", "_group_role"];
_position = _unit call armatak_client_fnc_extractClientPosition;
_uuid = _unit call armatak_fnc_extract_uuid;
_eud_cot = [_uuid, _position select 1, _position select 2, _position select 3, _callsign, _group_name, _group_role, _position select 5, _position select 6];
"armatak" callExtension ["tcp_socket:cot:eud", [_eud_cot]];
@@ -5,9 +5,9 @@
params["_group"];
{
_callsign = [_x] call armatak_fnc_extract_callsign;
_callsign = [_x] call armatak_fnc_extract_unit_callsign;
_group_name = [_group] call armatak_fnc_extract_group_color;
_group_role = [_x] call armatak_fnc_extract_group_role;
[_x, _callsign, _group_name, _group_role] call armatak_fnc_send_human_cot;
[_x, _callsign, _group_name, _group_role] call armatak_fnc_send_eud_cot;
} forEach (units _group);
@@ -1,12 +0,0 @@
// function name: armatak_fnc_extract_human_cot_info
// function author: Valmo
// function description: Gets the information necessary for generating the Human Cursor Over Time
params ["_unit", "_callsign", "_group_name", "_group_role"];
_position = _unit call armatak_fnc_extract_position;
_uuid = _unit call armatak_fnc_extract_uuid;
_human_cot = [_uuid, _position select 0, _position select 1, _position select 2, _callsign, _group_name, _group_role, _position select 3, speed player / 3.6];
"armatak" callExtension ["cot_router:send_human_cot", [_human_cot]];
@@ -4,9 +4,11 @@
params ["_unit", "_type", "_callsign"];
_unit_position = _unit call armatak_fnc_extract_position;
_unit_position = _unit call armatak_client_fnc_extractClientPosition;
_video_url = [_unit] call armatak_fnc_extract_marker_video_url;
_uuid = _unit call armatak_fnc_extract_uuid;
_marker_cot = [_uuid, _type, _unit_position select 0, _unit_position select 1, _unit_position select 2, _callsign, _unit_position select 3, speed _unit / 3.6];
_marker_cot = [_uuid, _type, _unit_position select 1, _unit_position select 2, _unit_position select 3, _callsign, _unit_position select 5, _unit_position select 6, _video_url];
"armatak" callExtension ["cot_router:send_marker_cot", [_marker_cot]];
"armatak" callExtension ["tcp_socket:cot:marker", [_marker_cot]];
@@ -0,0 +1,55 @@
// function name: armatak_fnc_send_uas_sensor_cot
// function author: Valmo / ArmaTAK contributors
// function description:
// Sends a b-m-p-s-p-loc CoT event every router tick (1 s) for a drone.
// This is the "sensor position" event consumed by the ATAK UAS Tool to:
// - Draw the FOV cone on the moving map.
// - Compute four-corners for AR marker overlay on the video feed.
// - Show the SPoI (Sensor Point of Interest) crosshair.
//
// The event references the drone's b-i-v video endpoint via the drone UUID,
// so armatak_fnc_send_uas_video_cot must also be called for the same drone.
//
// Exits silently when "armatak_attribute_video_url" is not set, which keeps
// the behavior identical to the old fn_send_drone_cot for drones without a
// configured video stream.
//
// Arguments:
// 0: _drone <OBJECT> The drone object.
//
// Return value: none
params ["_drone"];
private _video_url = _drone getVariable ["armatak_attribute_video_url", ""];
if (_video_url == "") exitWith {};
private _uuid = _drone call armatak_fnc_extract_uuid;
private _sensor_uid = _uuid + "-sensor";
private _callsign = [_drone] call armatak_fnc_extract_marker_callsign;
private _pos = (getPos _drone) call armatak_client_fnc_convertClientLocation;
private _lat = _pos select 0;
private _lon = _pos select 1;
private _hae = _pos select 2;
private _azimuth = parseNumber ((getDir _drone) toFixed 0);
private _allTurrets = [_drone, false] call BIS_fnc_allTurrets;
if (count _allTurrets > 0) then {
private _firstTurretPath = _allTurrets select 0;
private _turretWeapons = _drone weaponsTurret _firstTurretPath;
if (_turretWeapons isNotEqualTo []) then {
private _tDir = _drone weaponDirection (_turretWeapons select 0);
if (!((_tDir select 0) == 0 && (_tDir select 1) == 0)) then {
_azimuth = round (((_tDir select 0) atan2 (_tDir select 1) + 360) mod 360);
};
};
};
private _fov = _drone getVariable ["armatak_uas_fov", 60];
private _range = round (((getPosATL _drone) select 2) max 1);
private _payload = [_sensor_uid, _uuid, _callsign, _lat, _lon, _hae, _azimuth, _fov, _range];
"armatak" callExtension ["tcp_socket:cot:uas_sensor", [_payload]];
@@ -0,0 +1,30 @@
// function name: armatak_fnc_send_uas_video_cot
// function author: Valmo / ArmaTAK contributors
// function description:
// Sends a b-i-v CoT event that declares the RTSP video endpoint for a drone.
// The ATAK UAS Tool picks this up and shows the drone in its UAS list with
// the associated video feed available for playback.
//
// The drone entity MUST have the variable "armatak_attribute_video_url" set
// to a valid RTSP URL, e.g.:
// _drone setVariable ["armatak_attribute_video_url", "rtsp://192.168.1.10:8554/live/drone1"];
// or via the 3DEN attribute "Video URL (RTSP)" in the ARMA Team Awareness Kit
// attribute category.
//
// If the variable is absent or empty the function exits silently.
//
// Arguments:
// 0: _drone <OBJECT> The drone object.
//
// Return value: none
params ["_drone"];
private _video_url = _drone getVariable ["armatak_attribute_video_url", ""];
if (_video_url == "") exitWith {};
private _uuid = _drone call armatak_fnc_extract_uuid;
private _callsign = [_drone] call armatak_fnc_extract_marker_callsign;
private _payload = [_uuid, _callsign, _video_url];
"armatak" callExtension ["tcp_socket:cot:uas_video", [_payload]];
@@ -0,0 +1,10 @@
_armatak_tcp_socket_is_running = missionNamespace getVariable "armatak_tcp_socket_is_running";
if (_armatak_tcp_socket_is_running) then {
missionNamespace setVariable ["armatak_tcp_socket_is_running", false];
"armatak" callExtension ["tcp_socket:stop", []];
} else {
_warning = format ["<t color='#FF0021'>ARMATAK</t><br/> %1", "There is no TCP Socket running to be stopped"];
[[_warning, 1.5]] call CBA_fnc_notify;
};
@@ -1,43 +0,0 @@
// function name: armatak_fnc_extract_callsign
// function author: Valmo
// function description: Gets the unit name or classname to be used as TAK callsign
params["_unit"];
private _callsign = "";
if (roleDescription _unit != "") then {
_callsign = ([name _unit] call armatak_fnc_shorten_name) + " | " + roleDescription _unit;
} else {
_callsign = name _unit;
if (_callsign == "Error: No unit") then {
_callsign = getText (configFile >> "CfgVehicles" >> typeOf _unit >> "displayName");
};
};
if ((([_unit] call BIS_fnc_objectType) select 0) == "Vehicle") then {
_callsign = getText (configFile >> "CfgVehicles" >> typeOf _unit >> "displayName");
if (!isNull driver _unit) then {
_callsign = getText (configFile >> "CfgVehicles" >> typeOf _unit >> "displayName") + " | " + ([name (driver _unit)] call armatak_fnc_shorten_name);
};
};
if (unitIsUAV _unit) then {
_callsign = getText (configFile >> "CfgVehicles" >> typeOf _unit >> "displayName");
if (isUAVConnected _unit) then {
_callsign = (_callsign) + "[ON]";
} else {
_callsign = (_callsign) + "[OFF]";
}
};
_atak_pre_defined_callsign = _unit getVariable "_atak_callsign";
if (!isNil "_atak_pre_defined_callsign") then {
_callsign = _atak_pre_defined_callsign;
};
_callsign
@@ -1,9 +1,11 @@
#include "..\..\script_component.hpp"
params["_group"];
_group_name = _group getVariable "_atak_group_name";
_group_name = _group getVariable QGVAR(group_name);
if (isNil "_group_name") then {
_group_colors = missionNamespace getVariable "_group_colors";
_group_colors = missionNamespace getVariable QGVAR(group_colors);
_group_name = selectRandom _group_colors;
if (count _group_colors > 0) then {
@@ -14,11 +16,11 @@ if (isNil "_group_name") then {
_group_colors deleteAt _randomIndex;
_group_name = _selectedColor;
_group setVariable ["_atak_group_name", _group_name];
missionNamespace setVariable ["_group_colors", _group_colors]
_group setVariable [QGVAR(group_name), _group_name];
missionNamespace setVariable [QGVAR(group_colors), _group_colors]
} else {
_group_name = "Red";
_group setVariable ["_atak_group_name", _group_name];
_group setVariable [QGVAR(group_name), _group_name];
};
};
@@ -1,9 +1,10 @@
params["_unit"];
_group = group _unit;
_group_roles = ["Team Member", "Team Lead", "HQ", "Sniper", "Medic", "Forward Observer", "RTO", "K9"];
_group_role = "Team Member";
if (["SpecialOperative", (configFile >> "CfgVehicles" >> typeOf _unit >> "role") call BIS_fnc_getCfgData, false] call BIS_fnc_inString) then {
if (["SpecialOperative", (configOf _unit >> "role") call BIS_fnc_getCfgData, false] call BIS_fnc_inString) then {
_group_role = _group_roles select 5;
};
@@ -19,7 +20,7 @@ if (((backpack _unit) isKindOf "TFAR_Bag_Base") or (["radio", typeOf _unit, fals
_group_role = _group_roles select 6;
};
if ((["sniper", typeOf _unit, false] call BIS_fnc_inString) or (["marksman", (configFile >> "CfgVehicles" >> typeOf _unit >> "role") call BIS_fnc_getCfgData, false] call BIS_fnc_inString) or (["sharpshooter", typeOf _unit, false] call BIS_fnc_inString)) then {
if ((["sniper", typeOf _unit, false] call BIS_fnc_inString) or (["marksman", (configOf _unit >> "role") call BIS_fnc_getCfgData, false] call BIS_fnc_inString) or (["sharpshooter", typeOf _unit, false] call BIS_fnc_inString)) then {
_group_role = _group_roles select 3;
};
@@ -34,7 +35,7 @@ if (["officer", typeOf _unit, false] call BIS_fnc_inString) then {
_pre_defined_role = _unit getVariable "_atak_group_role";
if (!isNil "_pre_defined_role") then {
_callsign = _pre_defined_callsign;
_callsign = _pre_defined_role;
};
_group_role
@@ -0,0 +1,33 @@
// function name: armatak_fnc_extract_marker_callsign
// function author: Valmo
// function description: Gets the unit name or classname to be used as TAK callsign in a Marker
params["_unit"];
private _callsign = "";
if ((([_unit] call BIS_fnc_objectType) select 0) == "Vehicle") then {
_callsign = getText (configOf _unit >> "displayName");
if (!isNull driver _unit) then {
_callsign = getText (configOf _unit >> "displayName") + " | " + ([name (driver _unit)] call armatak_fnc_shorten_name);
};
};
if (unitIsUAV _unit) then {
_callsign = getText (configOf _unit >> "displayName");
if (isUAVConnected _unit) then {
_callsign = (_callsign) + "[ON]";
} else {
_callsign = (_callsign) + "[OFF]";
}
};
armatak_attribute_marker_callsign = _unit getVariable "armatak_attribute_marker_callsign";
if (!isNil "armatak_attribute_marker_callsign" or armatak_attribute_marker_callsign != '') then {
_callsign = armatak_attribute_marker_callsign;
};
_callsign
@@ -0,0 +1,13 @@
// function name: armatak_fnc_extract_marker_video_url
// function author: Codex
// function description: Gets the marker video URL configured in 3DEN for a vehicle
params ["_unit"];
private _videoUrl = _unit getVariable ["armatak_attribute_marker_video_url", ""];
if (isNil "_videoUrl") exitWith {
""
};
_videoUrl
@@ -1,16 +0,0 @@
// function name: armatak_fnc_extract_position
// function author: Valmo
// function description: Receives a player's unit as param and return the information array for SIMTAK
params["_unit"];
private _location = (getPos _unit) call armatak_fnc_convert_location;
private _atak_latitude = _location select 0;
private _atak_longitude = _location select 1;
private _atak_altitude = _location select 2;
private _atak_bearing = parseNumber ((getDir _unit) toFixed 0);
_unit_info = [_atak_latitude,_atak_longitude,_atak_altitude,_atak_bearing];
_unit_info
@@ -7,8 +7,15 @@ params["_unit"];
private _affiliation = "f";
private _type = "G";
private _role = "a-f-G-U-C-I";
private _side = side _unit;
switch (str side _unit) do {
if (isNil {
_unit getVariable "armatak_current_side"
}) then {
_side = _unit getVariable "armatak_current_side";
};
switch (str _side) do {
case "WEST": {
_affiliation = "f";
};
@@ -22,7 +29,7 @@ switch (str side _unit) do {
_affiliation = "u";
};
default {
_affiliation = "f";
_affiliation = "u";
};
};
@@ -110,4 +117,10 @@ if ((typeOf (vehicle _unit) != typeOf _unit) or ((_unit_type select 0) == "Vehic
_role = "a-" + _affiliation + "-" + _type;
armatak_attribute_marker_type = _unit getVariable "armatak_attribute_marker_type";
if (!isNil "armatak_attribute_marker_type" or armatak_attribute_marker_type != '') then {
_role = armatak_attribute_marker_type;
};
_role
@@ -0,0 +1,27 @@
params["_unit"];
_target = getSensorTargets (_unit);
{
_unit = _x select 0;
_position = _x select 1;
_status = _x select 2;
if (isNil {
_unit getVariable "armatak_current_side"
}) then {
_unit setVariable ["armatak_current_side", side _unit];
};
if (_status != "destroyed" && !(_unit in armatak_server_syncedUnits)) then {
_unit_position = _unit call armatak_client_fnc_extractClientPosition;
_uuid = _unit call armatak_fnc_extract_uuid;
_type = _unit call armatak_fnc_extract_role;
_callsign = getText (configOf _unit >> "displayName");
_marker_cot = [_uuid, _type, _unit_position select 1, _unit_position select 2, _unit_position select 3, _callsign, _unit_position select 5, _unit_position select 6];
"armatak" callExtension ["tcp_socket:cot:marker", [_marker_cot]];
};
} forEach _target;
@@ -0,0 +1,29 @@
// function name: armatak_fnc_extract_unit_callsign
// function author: Valmo
// function description: Gets the unit name or classname to be used as TAK callsign from a unit
params["_unit"];
private _callsign = "";
if (roleDescription _unit != "") then {
_callsign = ([name _unit] call armatak_fnc_shorten_name) + " | " + roleDescription _unit;
} else {
_callsign = name _unit;
if (_callsign == "Error: No unit") then {
_callsign = getText (configOf _unit >> "displayName");
};
};
if (side _unit == east) then {
_callsign = getText (configOf _unit >> "displayName");
};
armatak_attribute_unit_callsign = _unit getVariable "armatak_attribute_unit_callsign";
if (!isNil "armatak_attribute_unit_callsign" or armatak_attribute_unit_callsign != '') then {
_callsign = armatak_attribute_unit_callsign;
};
_callsign
-78
View File
@@ -1,78 +0,0 @@
params [
["_logic", objNull, [objNull]],
["_units", [], [[]]],
["_activated", true, [true]]
];
if (isServer) exitWith {
_warning = format ["<t color='#FF8021'>ARMATAK</t><br/> %1", "Connecting to TAK Server TCP Socket..."];
[[_warning, 1.5]] call CBA_fnc_notify;
addMissionEventHandler ["ExtensionCallback", {
params ["_name", "_function", "_data"];
if (_name == "armatak_tcp_socket") then {
_warning = format ["<t color='#00FF21'>ARMATAK</t><br/> %1", _function];
[[_warning, 1.5]] call CBA_fnc_notify;
};
if (_name == "armatak_tcp_socket_error") then {
_warning = format ["<t color='#FF0021'>ARMATAK</t><br/> %1", _function];
[[_warning, 1.5]] call CBA_fnc_notify;
};
if (_name == "armatak_video") then {
_warning = format ["<t color='#00FF21'>ARMATAK</t><br/> %1", _function];
[[_warning, 1.5]] call CBA_fnc_notify;
};
if (_name == "armatak_video_error") then {
_warning = format ["<t color='#FF0021'>ARMATAK</t><br/> %1", _function];
[[_warning, 1.5]] call CBA_fnc_notify;
};
}];
_tak_server_instance_address = _logic getVariable "armatak_module_tak_server_instance_address";
_tak_server_instance_port = _logic getVariable "armatak_module_tak_server_instance_port";
_tak_server_fulladdress = _tak_server_instance_address + ":" + (str _tak_server_instance_port);
missionNamespace setVariable ["_atak_server_instance", _tak_server_fulladdress];
missionNamespace setVariable ["_group_colors", ["White", "Yellow", "Orange", "Magenta", "Red", "Maroon", "Purple", "DarkBlue", "Blue", "Cyan", "Teal", "Green", "DarkGreen", "Brown"]];
"armatak" callExtension ["cot_router:start", [_tak_server_fulladdress]];
_syncUnits = synchronizedObjects _logic;
missionNamespace setVariable ["_armatak_marked_units", _syncUnits];
_syncedUnits = missionNamespace getVariable "_armatak_marked_units";
[{
_syncedUnits = missionNamespace getVariable "_armatak_marked_units";
{
_objectType = _x call BIS_fnc_objectType;
if ((_objectType select 0) == "Soldier") then {
_callsign = [_x] call armatak_fnc_extract_callsign;
_group_name = [group _x] call armatak_fnc_extract_group_color;
_group_role = [_x] call armatak_fnc_extract_group_role;
[_x, _callsign, _group_name, _group_role] call armatak_fnc_send_human_cot;
[_x] call armatak_fnc_send_digital_pointer_cot;
};
if ((_objectType select 0) == "Vehicle") then {
_atak_type = [_x] call armatak_fnc_extract_role;
_callsign = [_x] call armatak_fnc_extract_callsign;
[_x, _atak_type, _callsign] call armatak_fnc_send_marker_cot;
};
if (unitIsUAV _x) then {
[_x] call armatak_fnc_send_drone_cot;
[_x] call armatak_fnc_send_digital_pointer_cot;
};
} forEach _syncedUnits;
}, 2, []] call CBA_fnc_addPerFrameHandler;
};
true;
-3
View File
@@ -1,3 +0,0 @@
params[_type, _message];
"armatak" callExtension ["log", [_type, _message]]
-73
View File
@@ -1,73 +0,0 @@
params [
["_logic", objNull, [objNull]],
["_units", [], [[]]],
["_activated", true, [true]]
];
if (isServer) exitWith {
armatak_module_mediamtx_video_stream_instance_address = _logic getVariable "armatak_module_mediamtx_video_stream_instance_address";
armatak_module_mediamtx_video_stream_instance_port = _logic getVariable "armatak_module_mediamtx_video_stream_instance_port";
armatak_module_mediamtx_video_stream_instance_auth_user = _logic getVariable "armatak_module_mediamtx_video_stream_instance_auth_user";
armatak_module_mediamtx_video_stream_instance_auth_pass = _logic getVariable "armatak_module_mediamtx_video_stream_instance_auth_pass";
missionNamespace setVariable ["armatak_mediamtx_video_stream_instance_address", armatak_module_mediamtx_video_stream_instance_address];
missionNamespace setVariable ["armatak_mediamtx_video_stream_instance_port", armatak_module_mediamtx_video_stream_instance_port];
missionNamespace setVariable ["armatak_mediamtx_video_stream_instance_auth_user", armatak_module_mediamtx_video_stream_instance_auth_user];
missionNamespace setVariable ["armatak_mediamtx_video_stream_instance_auth_pass", armatak_module_mediamtx_video_stream_instance_auth_pass];
_startAction = [
"ArmatakStartStream",
"Start Video Feed",
"",
{
_uuid = (_this select 0) call armatak_fnc_extract_uuid;
armatak_mediamtx_video_stream_instance_address = missionNamespace getVariable "armatak_mediamtx_video_stream_instance_address";
armatak_mediamtx_video_stream_instance_port = missionNamespace getVariable "armatak_mediamtx_video_stream_instance_port";
armatak_mediamtx_video_stream_instance_auth_user = missionNamespace getVariable "armatak_mediamtx_video_stream_instance_auth_user";
armatak_mediamtx_video_stream_instance_auth_pass = missionNamespace getVariable "armatak_mediamtx_video_stream_instance_auth_pass";
"armatak" callExtension ["video_stream:start", [armatak_mediamtx_video_stream_instance_address, armatak_mediamtx_video_stream_instance_port, _uuid, armatak_mediamtx_video_stream_instance_auth_user, armatak_mediamtx_video_stream_instance_auth_pass]];
(_this select 0) setVariable ["armatak_video_feed_is_streaming", true];
},
{
(_this select 0) getVariable "armatak_video_feed_is_streaming" == false
}
] call ace_interact_menu_fnc_createAction;
[
"Man",
1,
["ACE_SelfActions"],
_startAction,
true
] call ace_interact_menu_fnc_addActionToClass;
_stopAction = [
"ArmatakStopStream",
"Stop Video Feed",
"",
{
"armatak" callExtension ["video_stream:stop", []];
(_this select 0) setVariable ["armatak_video_feed_is_streaming", false];
},
{
(_this select 0) getVariable "armatak_video_feed_is_streaming"
}
] call ace_interact_menu_fnc_createAction;
[
"Man",
1,
["ACE_SelfActions"],
_stopAction,
true
] call ace_interact_menu_fnc_addActionToClass;
if (isMultiplayer) then {
{
_x setVariable ["armatak_video_feed_is_streaming", false];
} forEach playableUnits;
} else {
player setVariable ["armatak_video_feed_is_streaming", false];
};
};
true;
+3
View File
@@ -0,0 +1,3 @@
params["_type", "_message"];
"armatak" callExtension ["log", [_type, _message]]
+21
View File
@@ -0,0 +1,21 @@
#include "..\script_component.hpp"
params ["_message", "_type", ["_title", "ARMATAK"]];
switch (_type) do {
case "success": {
_warning = format ["<t color='#00FF21'>ARMATAK - %1</t><br/> %2", _title, _message];
[[_warning, 1.5]] call CBA_fnc_notify;
};
case "warning": {
_warning = format ["<t color='#ffff16'>ARMATAK - %1</t><br/> %2", _title, _message];
[[_warning, 1.5]] call CBA_fnc_notify;
};
case "error": {
_warning = format ["<t color='#FF0021'>ARMATAK - %1</t><br/> %2", _title, _message];
[[_warning, 1.5]] call CBA_fnc_notify;
};
default {
systemChat format ["%1 - %2", _title, _message];
};
};
@@ -1,61 +0,0 @@
params["_latitude", "_longitude", "_altitude"];
_position = [_latitude, _longitude, _altitude];
_realLocation = null;
switch (toLower worldName) do {
case "altis": {
_realLocation = _position call armatak_fnc_convert_to_altis;
};
case "stratis": {
_realLocation = _position call armatak_fnc_convert_to_stratis;
};
case "malden": {
_realLocation = _position call armatak_fnc_convert_to_malden;
};
case "vr": {
_realLocation = _position call armatak_fnc_convert_to_vr;
};
case "cucui": {
_realLocation = _position call armatak_fnc_convert_to_cucui;
};
case "chernarus": {
_realLocation = _position call armatak_fnc_convert_to_chernarus;
};
case "chernarus_summer": {
_realLocation = _position call armatak_fnc_convert_to_chernarus;
};
case "chernarus_winter": {
_realLocation = _position call armatak_fnc_convert_to_chernarus;
};
case "bootcamp_acr": {
_realLocation = _position call armatak_fnc_convert_to_bukovina;
};
case "woodland_acr": {
_realLocation = _position call armatak_fnc_convert_to_bystrika;
};
case "mountains_acr": {
_realLocation = _position call armatak_fnc_convert_to_takistan_montains;
};
case "sara_dbe1": {
_realLocation = _position call armatak_fnc_convert_to_united_sahrani;
};
case "saralite": {
_realLocation = _position call armatak_fnc_convert_to_southen_sahrani;
};
case "enoch": {
_realLocation = _position call armatak_fnc_convert_to_livonia;
};
case "kunduz": {
_realLocation = _position call armatak_fnc_convert_to_kunduz;
};
default {
_warning = format ["<t color='#FF8021'>ARMATAK</t><br/> %1", "Unsupported Map"];
[[_warning, 1.5]] call CBA_fnc_notify;
_realLocation = [0, 0, 0];
};
};
_realLocation
@@ -0,0 +1,23 @@
params["_latitude", "_longitude", "_altitude"];
_playerPosition = [_latitude, _longitude, _altitude];
_playerLatitude = _playerPosition select 0;
_playerLongitude = _playerPosition select 1;
_playerMaxLatitude = 20480;
_playerMaxLongitude = 20480;
_MapMaxLongitude = 33.728772;
_MapMinLongitude = 33.542815;
_MapMaxLatitude = 63.169746;
_MapMinLatitude = 62.938820;
_LongitudeDifference = _MapMaxLongitude - _MapMinLongitude;
_LatitudeDifference = _MapMaxLatitude - _MapMinLatitude;
_RealLongitude = (_playerLongitude / _playerMaxLongitude) * _LongitudeDifference + _MapMinLongitude;
_RealLatitude = (_playerLatitude / _playerMaxLatitude) * _LatitudeDifference + _MapMinLatitude;
[_RealLongitude, _RealLatitude, _playerPosition select 2]
@@ -0,0 +1,23 @@
params["_latitude", "_longitude", "_altitude"];
_playerPosition = [_latitude, _longitude, _altitude];
_playerLatitude = _playerPosition select 0;
_playerLongitude = _playerPosition select 1;
_playerMaxLatitude = 20480;
_playerMaxLongitude = 20480;
_MapMaxLatitude = -67.765153;
_MapMinLatitude = -68.223664;
_MapMaxLongitude = 10.593815;
_MapMinLongitude = 10.137466;
_LongitudeDifference = _MapMaxLongitude - _MapMinLongitude;
_LatitudeDifference = _MapMaxLatitude - _MapMinLatitude;
_RealLongitude = (_playerLongitude / _playerMaxLongitude) * _LongitudeDifference + _MapMinLongitude;
_RealLatitude = (_playerLatitude / _playerMaxLatitude) * _LatitudeDifference + _MapMinLatitude;
[_RealLongitude, _RealLatitude, _playerPosition select 2]
@@ -0,0 +1,30 @@
params ["_longitudeInGame", "_latitudeInGame", "_altitude"];
private _mapWidth = 8192;
private _mapHeight = 8192;
// SW corner (used as origin)
private _SW_lat = 63.005389;
private _SW_lon = 22.638957;
// SE corner
private _SE_lat = 63.010092;
private _SE_lon = 22.800107;
// NW corner
private _NW_lat = 63.078713;
private _NW_lon = 22.628542;
private _edgeSE_lat = _SE_lat - _SW_lat;
private _edgeSE_lon = _SE_lon - _SW_lon;
private _edgeNW_lat = _NW_lat - _SW_lat;
private _edgeNW_lon = _NW_lon - _SW_lon;
private _fx = _longitudeInGame / _mapWidth;
private _fy = _latitudeInGame / _mapHeight;
private _realLat = _SW_lat + (_fx * _edgeSE_lat) + (_fy * _edgeNW_lat);
private _realLon = _SW_lon + (_fx * _edgeSE_lon) + (_fy * _edgeNW_lon);
[_realLat, _realLon, _altitude]
@@ -4,16 +4,16 @@ private _mapWidth = 5120;
private _mapHeight = 5120;
// SW corner (used as origin)
private _SW_lat = 36.588437;
private _SW_lon = 68.834763;
private _SW_lat = 36.581566;
private _SW_lon = 68.839770;
// SE corner
private _SE_lat = 36.574950;
private _SE_lon = 68.899151;
private _SE_lat = 36.581566;
private _SE_lon = 68.905867;
// NW corner
private _NW_lat = 36.640080;
private _NW_lon = 68.847941;
private _NW_lat = 36.633309;
private _NW_lon = 68.839770;
private _edgeSE_lat = _SE_lat - _SW_lat;
private _edgeSE_lon = _SE_lon - _SW_lon;
@@ -0,0 +1,30 @@
params ["_longitudeInGame", "_latitudeInGame", "_altitude"];
private _mapWidth = 10240;
private _mapHeight = 10240;
// SW corner (used as origin)
private _SW_lat = 36.547662;
private _SW_lon = 68.802314;
// SE corner
private _SE_lat = 36.547662;
private _SE_lon = 68.916671;
// NW corner
private _NW_lat = 36.639935;
private _NW_lon = 68.802314;
private _edgeSE_lat = _SE_lat - _SW_lat;
private _edgeSE_lon = _SE_lon - _SW_lon;
private _edgeNW_lat = _NW_lat - _SW_lat;
private _edgeNW_lon = _NW_lon - _SW_lon;
private _fx = _longitudeInGame / _mapWidth;
private _fy = _latitudeInGame / _mapHeight;
private _realLat = _SW_lat + (_fx * _edgeSE_lat) + (_fy * _edgeNW_lat);
private _realLon = _SW_lon + (_fx * _edgeSE_lon) + (_fy * _edgeNW_lon);
[_realLat, _realLon, _altitude]
@@ -0,0 +1,23 @@
params["_latitude", "_longitude", "_altitude"];
_playerPosition = [_latitude, _longitude, _altitude];
_playerLatitude = _playerPosition select 0;
_playerLongitude = _playerPosition select 1;
_playerMaxLongitude = 4992;
_playerMaxLatitude = 4992;
_MapMaxLongitude = -99.722665;
_MapMinLongitude = -99.775505;
_MapMaxLatitude = 32.159272;
_MapMinLatitude = 32.114011;
_LongitudeDifference = _MapMaxLongitude - _MapMinLongitude;
_LatitudeDifference = _MapMaxLatitude - _MapMinLatitude;
_RealLongitude = (_playerLongitude / _playerMaxLongitude) * _LongitudeDifference + _MapMinLongitude;
_RealLatitude = (_playerLatitude / _playerMaxLatitude) * _LatitudeDifference + _MapMinLatitude;
[_RealLongitude, _RealLatitude, _playerPosition select 2]
@@ -0,0 +1,30 @@
params ["_longitudeInGame", "_latitudeInGame", "_altitude"];
private _mapWidth = 11264;
private _mapHeight = 11264;
// SW corner (used as origin)
private _SW_lat = -51.736078;
private _SW_lon = -57.915032;
// SE corner
private _SE_lat = -51.736078;
private _SE_lon = -58.077879;
// NW corner
private _NW_lat = -51.634750;
private _NW_lon = -58.077879;
private _edgeSE_lat = _SE_lat - _SW_lat;
private _edgeSE_lon = _SE_lon - _SW_lon;
private _edgeNW_lat = _NW_lat - _SW_lat;
private _edgeNW_lon = _NW_lon - _SW_lon;
private _fx = _longitudeInGame / _mapWidth;
private _fy = _latitudeInGame / _mapHeight;
private _realLat = _SW_lat + (_fx * _edgeSE_lat) + (_fy * _edgeNW_lat);
private _realLon = _SW_lon + (_fx * _edgeSE_lon) + (_fy * _edgeNW_lon);
[_realLat, _realLon, _altitude]
@@ -0,0 +1,30 @@
params ["_longitudeInGame", "_latitudeInGame", "_altitude"];
private _mapWidth = 16384;
private _mapHeight = 16384;
// SW corner (used as origin)
private _SW_lat = -51.806546;
private _SW_lon = -57.939747;
// SE corner
private _SE_lat = -51.806546;
private _SE_lon = -57.701978;
// NW corner
private _NW_lat = -51.658913;
private _NW_lon = -57.939747;
private _edgeSE_lat = _SE_lat - _SW_lat;
private _edgeSE_lon = _SE_lon - _SW_lon;
private _edgeNW_lat = _NW_lat - _SW_lat;
private _edgeNW_lon = _NW_lon - _SW_lon;
private _fx = _longitudeInGame / _mapWidth;
private _fy = _latitudeInGame / _mapHeight;
private _realLat = _SW_lat + (_fx * _edgeSE_lat) + (_fy * _edgeNW_lat);
private _realLon = _SW_lon + (_fx * _edgeSE_lon) + (_fy * _edgeNW_lon);
[_realLat, _realLon, _altitude]
@@ -0,0 +1,30 @@
params ["_longitudeInGame", "_latitudeInGame", "_altitude"];
private _mapWidth = 10240;
private _mapHeight = 10240;
// SW corner (used as origin)
private _SW_lat = -51.863358;
private _SW_lon = -59.054585;
// SE corner
private _SE_lat = -51.863358;
private _SE_lon = -58.906155;
// NW corner
private _NW_lat = -51.771493;
private _NW_lon = -59.054585;
private _edgeSE_lat = _SE_lat - _SW_lat;
private _edgeSE_lon = _SE_lon - _SW_lon;
private _edgeNW_lat = _NW_lat - _SW_lat;
private _edgeNW_lon = _NW_lon - _SW_lon;
private _fx = _longitudeInGame / _mapWidth;
private _fy = _latitudeInGame / _mapHeight;
private _realLat = _SW_lat + (_fx * _edgeSE_lat) + (_fy * _edgeNW_lat);
private _realLon = _SW_lon + (_fx * _edgeSE_lon) + (_fy * _edgeNW_lon);
[_realLat, _realLon, _altitude]
@@ -0,0 +1,23 @@
params["_latitude", "_longitude", "_altitude"];
_playerPosition = [_latitude, _longitude, _altitude];
_playerLatitude = _playerPosition select 0;
_playerLongitude = _playerPosition select 1;
_playerMaxLongitude = 5120;
_playerMaxLatitude = 5120;
_MapMaxLatitude = -51.619725;
_MapMinLatitude = -51.664223;
_MapMaxLongitude = -58.394630;
_MapMinLongitude = -58.469580;
_LongitudeDifference = _MapMaxLongitude - _MapMinLongitude;
_LatitudeDifference = _MapMaxLatitude - _MapMinLatitude;
_RealLongitude = (_playerLongitude / _playerMaxLongitude) * _LongitudeDifference + _MapMinLongitude;
_RealLatitude = (_playerLatitude / _playerMaxLatitude) * _LatitudeDifference + _MapMinLatitude;
[_RealLongitude, _RealLatitude, _playerPosition select 2]
@@ -0,0 +1,23 @@
params["_latitude", "_longitude", "_altitude"];
_playerPosition = [_latitude, _longitude, _altitude];
_playerLatitude = _playerPosition select 0;
_playerLongitude = _playerPosition select 1;
_playerMaxLatitude = 32768;
_playerMaxLongitude = 32768;
_MapMaxLongitude = 35.285485;
_MapMinLongitude = 34.927617;
_MapMaxLatitude = 70.445404;
_MapMinLatitude = 70.016783;
_LongitudeDifference = _MapMaxLongitude - _MapMinLongitude;
_LatitudeDifference = _MapMaxLatitude - _MapMinLatitude;
_RealLongitude = (_playerLongitude / _playerMaxLongitude) * _LongitudeDifference + _MapMinLongitude;
_RealLatitude = (_playerLatitude / _playerMaxLatitude) * _LatitudeDifference + _MapMinLatitude;
[_RealLongitude, _RealLatitude, _playerPosition select 2]
@@ -1,19 +1,19 @@
params ["_longitudeInGame", "_latitudeInGame", "_altitude"];
private _mapWidth = 30720;
private _mapHeight = 30720;
private _mapWidth = 8192;
private _mapHeight = 8192;
// SW corner (used as origin)
private _SW_lat = 39.456910;
private _SW_lon = 24.940792;
private _SW_lat = 39.458019;
private _SW_lon = 24.939314;
// SE corner
private _SE_lat = 39.459151;
private _SE_lon = 25.083440;
private _SE_lat = 39.458019;
private _SE_lon = 25.081992;
// NW corner
private _NW_lat = 39.567714;
private _NW_lon = 24.937866;
private _NW_lat = 39.568847;
private _NW_lon = 24.939314;
private _edgeSE_lat = _SE_lat - _SW_lat;
private _edgeSE_lon = _SE_lon - _SW_lon;
@@ -1,19 +1,19 @@
params ["_longitudeInGame", "_latitudeInGame", "_altitude"];
private _mapWidth = 30720;
private _mapHeight = 30720;
private _mapWidth = 15360;
private _mapHeight = 15360;
// SW corner (used as origin)
private _SW_lat = -19.086825;
private _SW_lon = 176.812772;
private _SW_lat = -19.086803;
private _SW_lon = 176.812619;
// SE corner
private _SE_lat = -19.086825;
private _SE_lon = 178.687920;
private _SE_lat = -19.086803;
private _SE_lon = 178.704583;
// NW corner
private _NW_lat = -17.196898;
private _NW_lon = 176.812622;
private _NW_lat = -17.196900;
private _NW_lon = 176.812619;
private _edgeSE_lat = _SE_lat - _SW_lat;
private _edgeSE_lon = _SE_lon - _SW_lon;
@@ -0,0 +1,23 @@
params["_latitude", "_longitude", "_altitude"];
_playerPosition = [_latitude, _longitude, _altitude];
_playerLatitude = _playerPosition select 0;
_playerLongitude = _playerPosition select 1;
_playerMaxLongitude = 20480;
_playerMaxLatitude = 20480;
_MapMaxLongitude = 48.351216;
_MapMinLongitude = 48.097496;
_MapMaxLatitude = 38.345389;
_MapMinLatitude = 37.956754;
_LongitudeDifference = _MapMaxLongitude - _MapMinLongitude;
_LatitudeDifference = _MapMaxLatitude - _MapMinLatitude;
_RealLongitude = (_playerLongitude / _playerMaxLongitude) * _LongitudeDifference + _MapMinLongitude;
_RealLatitude = (_playerLatitude / _playerMaxLatitude) * _LatitudeDifference + _MapMinLatitude;
[_RealLongitude, _RealLatitude, _playerPosition select 2]
-18
View File
@@ -1,18 +0,0 @@
if (!hasInterface) exitWith {};
_local_address = "armatak" callExtension ["local_ip", []] select 0;
player setVariable ["localAddress", _local_address];
player addEventHandler ["Respawn", {
params["_unit", "_corpse"];
[{
if (alive _this) then {
"armatak" callExtension ["websocket:location", [player call armatak_fnc_extract_position]];
};
}, 1, []] call CBA_fnc_addPerFrameHandler;
}];
[{
"armatak" callExtension ["websocket:location", [player call armatak_fnc_extract_position]];
}, 1, []] call CBA_fnc_addPerFrameHandler;
+17
View File
@@ -0,0 +1,17 @@
#define COMPONENT main
#define COMPONENT_BEAUTIFIED Main
#include "\armatak\armatak\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS
#ifdef DEBUG_ENABLED_MAIN
#define DEBUG_MODE_FULL
#endif
#ifdef DEBUG_SETTINGS_MAIN
#define DEBUG_SETTINGS DEBUG_SETTINGS_MAIN
#endif
#include "\z\ace\addons\main\script_macros.hpp"
+32
View File
@@ -0,0 +1,32 @@
// COMPONENT should be defined in the script_component.hpp and included BEFORE this hpp
#define MAINPREFIX armatak
#define PREFIX armatak
#include "script_version.hpp"
#define VERSION MAJOR.MINOR
#define VERSION_STR MAJOR.MINOR.PATCHLVL.BUILD
#define VERSION_AR MAJOR,MINOR,PATCHLVL,BUILD
#define PROJECT_AUTHOR QUOTE(Valmo Trindade)
// MINIMAL required version for the Mod. Components can specify others..
#define REQUIRED_VERSION 2.18
#define REQUIRED_CBA_VERSION {3,18,2}
#ifndef COMPONENT_BEAUTIFIED
#define COMPONENT_BEAUTIFIED COMPONENT
#endif
#ifdef SUBCOMPONENT_BEAUTIFIED
#define COMPONENT_NAME QUOTE(ARMATAK - COMPONENT_BEAUTIFIED - SUBCOMPONENT_BEAUTIFIED)
#else
#define COMPONENT_NAME QUOTE(ARMATAK - COMPONENT_BEAUTIFIED)
#endif
// Custom ARMATAK MACRO defines
#define EXTENSION_NAME QUOTE(armatak)
#define CALLEXT(var) EXTENSION_NAME callExtension [QUOTE(var),[]]
#define CALLEXTP(var1, var2) EXTENSION_NAME callExtension [QUOTE(var1), var2] select 0
+1 -1
View File
@@ -1,4 +1,4 @@
#define build 0
#define major 1
#define minor 0
#define minor 1
#define patch 0
+1
View File
@@ -0,0 +1 @@
armatak\armatak\addons\server
+11
View File
@@ -0,0 +1,11 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));
};
};
class Extended_PreInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_preInit));
};
};
+133
View File
@@ -0,0 +1,133 @@
class CfgVehicles {
class Logic;
class Module_F : Logic {
class AttributesBase {
class Edit;
class ModuleDescription;
};
class ModuleDescription;
};
class GVAR(moduleBase): Module_F {
author = PROJECT_AUTHOR;
category = QEGVAR(main,moduleCategory);
function = QUOTE({});
functionPriority = 1;
isGlobal = 1;
isTriggerActivated = 0;
scope = 1;
scopeCurator = 2;
};
class GVAR(connectionModuleBase): GVAR(moduleBase) {
scopeCurator = 0;
icon = "\a3\Modules_F_Curator\Data\iconRadio_ca.paa";
category = QEGVAR(main,moduleCategory);
functionPriority = 1;
isGlobal = 0;
isTriggerActivated = 1;
isDisposable = 1;
is3den = 0;
curatorCanAttach = 0;
curatorInfoType = "RscDisplayAttributeModuleNuke";
canSetArea = 0;
canSetAreaShape = 0;
canSetAreaHeight = 0;
};
class GVAR(tcpModule): GVAR(connectionModuleBase) {
scope = 2;
displayName = "CoT Router (TCP)";
function = QFUNC(3denTcpModuleConfig);
class Attributes: AttributesBase {
class GVAR(moduleInstanceAddress): Edit {
property = QGVAR(moduleInstanceAddress);
displayName = "TAK Server Address";
tooltip = "Hostname or IP address for the TAK or IronTAK server.";
typeName = "STRING";
defaultValue = "'localhost'";
};
class GVAR(moduleInstancePort): Edit {
property = QGVAR(moduleInstancePort);
displayName = "TAK Server TCP Port";
tooltip = "Port for the unauthenticated TCP socket.";
typeName = "NUMBER";
defaultValue = "8088";
};
class ModuleDescription: ModuleDescription {};
};
class ModuleDescription: ModuleDescription {
description = "Connect ArmaTAK to a TAK server over plain TCP.";
sync[] = {"LocationArea_F"};
};
};
class GVAR(enrollModule): GVAR(connectionModuleBase) {
scope = 2;
displayName = "CoT Router (Authenticated)";
function = QFUNC(3denEnrollModuleConfig);
class Attributes: AttributesBase {
class GVAR(moduleInstanceAddress): Edit {
property = QGVAR(moduleInstanceAddress);
displayname = "TAK Server Address";
tooltip = "Hostname or IP address used for enrollment and the final TLS connection.";
typeName = "STRING";
defaultValue = "'localhost'";
};
class GVAR(moduleEnrollmentPort): Edit {
property = QGVAR(moduleEnrollmentPort);
displayName = "Enrollment HTTPS Port";
tooltip = "Port used for GET /Marti/api/tls/config and POST /Marti/api/tls/signClient/v2.";
typeName = "NUMBER";
defaultValue = "8446";
};
class GVAR(moduleEnrollmentUsername): Edit {
property = QGVAR(moduleEnrollmentUsername);
displayName = "Enrollment Username";
tooltip = "Username used in Basic Auth for client certificate enrollment.";
typeName = "STRING";
defaultValue = "''";
};
class GVAR(moduleEnrollmentPassword): Edit {
property = QGVAR(moduleEnrollmentPassword);
displayName = "Enrollment Password";
tooltip = "Password used in Basic Auth for client certificate enrollment.";
typeName = "STRING";
defaultValue = "''";
};
class ModuleDescription: ModuleDescription {};
};
class ModuleDescription: ModuleDescription {
description = "Enroll a client certificate and connect ArmaTAK over mTLS.";
sync[] = {"LocationArea_F"};
};
};
class GVAR(tcpModuleCurator): GVAR(tcpModule) {
scope = 1;
scopeCurator = 2;
function = "";
displayName = "CoT Router (TCP, Zeus)";
curatorInfoType = "armatak_zeus_tcp_module_dialog";
};
class GVAR(enrollModuleCurator): GVAR(enrollModule) {
scope = 1;
scopeCurator = 2;
function = "";
displayName = "CoT Router (Authenticated, Zeus)";
curatorInfoType = "armatak_zeus_enroll_module_dialog";
};
class GVAR(markEntity): GVAR(moduleBase) {
curatorCanAttach = 1;
category = QEGVAR(main,moduleCategory);
displayname = "Mark Entity";
function = QFUNC(routerEntityAdd);
icon = "\a3\Modules_F_Curator\Data\iconRadio_ca.paa";
};
};
+7
View File
@@ -0,0 +1,7 @@
PREP(3denEnrollModuleConfig);
PREP(3denTcpModuleConfig);
PREP(routerEntityAdd);
PREP(routerEntityRemove);
PREP(startCotRouter);
PREP(ZeusEnrollModuleConfig);
PREP(ZeusTcpModuleConfig);
+9
View File
@@ -0,0 +1,9 @@
#include "script_component.hpp"
ADDON = false;
PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
ADDON = true;
+3
View File
@@ -0,0 +1,3 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"
+27
View File
@@ -0,0 +1,27 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {
QGVAR(tcpModule),
QGVAR(tcpModuleCurator),
QGVAR(enrollModule),
QGVAR(enrollModuleCurator),
QGVAR(markEntity)
};
weapons[] = {};
requiredAddons[] = {
"cba_main",
"ace_main",
"armatak_main"
};
requiredVersion = REQUIRED_VERSION;
author = PROJECT_AUTHOR;
url = "https://github.com/valmojr/armatak";
};
};
#include "CfgEventHandlers.hpp"
#include "dialog.hpp"
#include "CfgVehicles.hpp"
+244
View File
@@ -0,0 +1,244 @@
class RscText;
class RscBackground;
class RscButton;
class RscEdit;
class armatak_zeus_tcp_module_dialog {
idd = 999991;
movingEnable = 0;
class ControlsBackground {
class main_frame: RscBackground {
idc = 1800;
x = "0.386562 * safezoneW + safezoneX";
y = "0.29 * safezoneH + safezoneY";
w = "0.216563 * safezoneW";
h = "0.32 * safezoneH";
colorBackground[] = {0,0,0,0.45};
};
};
class Controls {
class address_text: RscText {
idc = 1000;
text = "TAK Server Address";
x = "0.391719 * safezoneW + safezoneX";
y = "0.332 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.033 * safezoneH";
};
class address_edit: RscEdit {
idc = 14000;
text = "localhost";
x = "0.391719 * safezoneW + safezoneX";
y = "0.365 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.044 * safezoneH";
colorBackground[] = {0,0,0,0.5};
};
class port_text: RscText {
idc = 1001;
text = "TAK Server Port";
x = "0.391719 * safezoneW + safezoneX";
y = "0.425 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.033 * safezoneH";
};
class port_edit: RscEdit {
idc = 14001;
text = "8088";
x = "0.391719 * safezoneW + safezoneX";
y = "0.458 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.044 * safezoneH";
colorBackground[] = {0,0,0,0.5};
};
class button_cancel: RscButton {
idc = 1601;
text = "Cancel";
action = "closeDialog 2;";
x = "0.551563 * safezoneW + safezoneX";
y = "0.535 * safezoneH + safezoneY";
w = "0.0464063 * safezoneW";
h = "0.055 * safezoneH";
};
class button_ok: RscButton {
idc = 1600;
text = "Ok";
action = QUOTE(call FUNC(ZeusTcpModuleConfig));
x = "0.5 * safezoneW + safezoneX";
y = "0.535 * safezoneH + safezoneY";
w = "0.0464063 * safezoneW";
h = "0.055 * safezoneH";
};
};
};
class armatak_zeus_enroll_module_dialog {
idd = 999992;
movingEnable = 0;
class ControlsBackground {
class main_frame: RscBackground {
idc = 1810;
x = "0.386562 * safezoneW + safezoneX";
y = "0.2 * safezoneH + safezoneY";
w = "0.216563 * safezoneW";
h = "0.52 * safezoneH";
colorBackground[] = {0,0,0,0.45};
};
};
class Controls {
class address_text: RscText {
idc = 1010;
text = "TAK Server Address";
x = "0.391719 * safezoneW + safezoneX";
y = "0.242 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.033 * safezoneH";
};
class address_edit: RscEdit {
idc = 14100;
text = "localhost";
x = "0.391719 * safezoneW + safezoneX";
y = "0.275 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.044 * safezoneH";
colorBackground[] = {0,0,0,0.5};
};
class enroll_port_text: RscText {
idc = 1011;
text = "Enrollment HTTPS Port";
x = "0.391719 * safezoneW + safezoneX";
y = "0.335 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.033 * safezoneH";
};
class enroll_port_edit: RscEdit {
idc = 14101;
text = "8446";
x = "0.391719 * safezoneW + safezoneX";
y = "0.368 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.044 * safezoneH";
colorBackground[] = {0,0,0,0.5};
};
class username_text: RscText {
idc = 1012;
text = "Enrollment Username";
x = "0.391719 * safezoneW + safezoneX";
y = "0.428 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.033 * safezoneH";
};
class username_edit: RscEdit {
idc = 14102;
text = "";
x = "0.391719 * safezoneW + safezoneX";
y = "0.461 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.044 * safezoneH";
colorBackground[] = {0,0,0,0.5};
};
class password_text: RscText {
idc = 1013;
text = "Enrollment Password";
x = "0.391719 * safezoneW + safezoneX";
y = "0.521 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.033 * safezoneH";
};
class password_edit: RscEdit {
idc = 14103;
text = "";
x = "0.391719 * safezoneW + safezoneX";
y = "0.554 * safezoneH + safezoneY";
w = "0.20625 * safezoneW";
h = "0.044 * safezoneH";
colorBackground[] = {0,0,0,0.5};
};
class button_cancel: RscButton {
idc = 1611;
text = "Cancel";
action = "closeDialog 2;";
x = "0.551563 * safezoneW + safezoneX";
y = "0.645 * safezoneH + safezoneY";
w = "0.0464063 * safezoneW";
h = "0.055 * safezoneH";
};
class button_ok: RscButton {
idc = 1610;
text = "Ok";
action = QUOTE(call FUNC(ZeusEnrollModuleConfig));
x = "0.5 * safezoneW + safezoneX";
y = "0.645 * safezoneH + safezoneY";
w = "0.0464063 * safezoneW";
h = "0.055 * safezoneH";
};
};
};
class armatak_zeus_custom_marker_dialog {
idd = 990991;
movingEnable = 0;
class Controls {
class RscFrame_1800: RscBackground
{
idc = 1800;
x = "0.37625 * safezoneW + safezoneX";
y = "0.357 * safezoneH + safezoneY";
w = "0.237187 * safezoneW";
h = "0.275 * safezoneH";
};
class RscEdit_1400: RscEdit
{
idc = 1400;
x = "0.386562 * safezoneW + safezoneX";
y = "0.423 * safezoneH + safezoneY";
w = "0.216563 * safezoneW";
h = "0.044 * safezoneH";
};
class RscText_1000: RscText
{
idc = 1000;
text = "Entity Callsign";
x = "0.386562 * safezoneW + safezoneX";
y = "0.379 * safezoneH + safezoneY";
w = "0.216563 * safezoneW";
h = "0.044 * safezoneH";
};
class RscText_1001: RscText
{
idc = 1001;
text = "Entity Type (only for vehicles)";
x = "0.386562 * safezoneW + safezoneX";
y = "0.467 * safezoneH + safezoneY";
w = "0.216563 * safezoneW";
h = "0.044 * safezoneH";
};
class RscEdit_1401: RscEdit
{
idc = 1401;
x = "0.386562 * safezoneW + safezoneX";
y = "0.511 * safezoneH + safezoneY";
w = "0.216563 * safezoneW";
h = "0.044 * safezoneH";
};
class RscButton_1600: RscButton
{
idc = 1600;
text = "Cancel";
x = "0.551562 * safezoneW + safezoneX";
y = "0.566 * safezoneH + safezoneY";
w = "0.0515625 * safezoneW";
h = "0.055 * safezoneH";
};
class RscButton_1601: RscButton
{
idc = 1601;
text = "OK";
x = "0.489687 * safezoneW + safezoneX";
y = "0.566 * safezoneH + safezoneY";
w = "0.0515625 * safezoneW";
h = "0.055 * safezoneH";
};
};
};
@@ -0,0 +1,37 @@
#include "..\script_component.hpp"
params [
["_logic", objNull, [objNull]],
["_units", [], [[]]],
["_activated", true, [true]]
];
if (isServer) exitWith {
if (missionNamespace getVariable ["armatak_tcp_socket_is_running", false]) exitWith {
["Socket was called twice", "error", "TCP Socket"] call EFUNC(main,notify);
};
["Connecting to authenticated TAK socket", "success", "TCP Socket"] call EFUNC(main,notify);
_tak_server_instance_address = _logic getVariable [QGVAR(moduleInstanceAddress), "localhost"];
_tak_server_enrollment_port = _logic getVariable [QGVAR(moduleEnrollmentPort), 8446];
_tak_server_enrollment_username = _logic getVariable [QGVAR(moduleEnrollmentUsername), ""];
_tak_server_enrollment_password = _logic getVariable [QGVAR(moduleEnrollmentPassword), ""];
"armatak" callExtension [
"tcp_socket:start_enroll_mtls",
[
_tak_server_instance_address,
_tak_server_instance_address,
str _tak_server_enrollment_port,
_tak_server_enrollment_username,
_tak_server_enrollment_password,
""
]
];
missionNamespace setVariable ["armatak_server_syncedUnits", synchronizedObjects _logic];
_tak_server_instance_address call FUNC(startCotRouter);
};
true
@@ -0,0 +1,26 @@
#include "..\script_component.hpp"
params [
["_logic", objNull, [objNull]],
["_units", [], [[]]],
["_activated", true, [true]]
];
if (isServer) exitWith {
if (missionNamespace getVariable ["armatak_tcp_socket_is_running", false]) exitWith {
["Socket was called twice", "error", "TCP Socket"] call EFUNC(main,notify);
};
["Connecting to TCP Socket", "success", "TCP Socket"] call EFUNC(main,notify);
_tak_server_instance_address = _logic getVariable [QGVAR(moduleInstanceAddress), "localhost"];
_tak_server_instance_port = _logic getVariable [QGVAR(moduleInstancePort), 8088];
_tak_server_fulladdress = _tak_server_instance_address + ":" + (str _tak_server_instance_port);
"armatak" callExtension ["tcp_socket:start", [_tak_server_fulladdress]];
missionNamespace setVariable ["armatak_server_syncedUnits", synchronizedObjects _logic];
_tak_server_fulladdress call FUNC(startCotRouter);
};
true
@@ -0,0 +1,33 @@
#include "..\script_component.hpp"
params ["_logic"];
if (missionNamespace getVariable ["armatak_tcp_socket_is_running", false]) exitWith {
["Socket was called twice", "error", "TCP Socket"] call EFUNC(main,notify);
closeDialog 1;
};
disableSerialization;
["Connecting to authenticated TAK socket", "success", "TCP Socket"] call EFUNC(main,notify);
_tak_server_instance_address = ctrlText 14100;
_tak_server_enrollment_port = ctrlText 14101;
_tak_server_enrollment_username = ctrlText 14102;
_tak_server_enrollment_password = ctrlText 14103;
"armatak" callExtension [
"tcp_socket:start_enroll_mtls",
[
_tak_server_instance_address,
_tak_server_instance_address,
_tak_server_enrollment_port,
_tak_server_enrollment_username,
_tak_server_enrollment_password,
""
]
];
_tak_server_instance_address call FUNC(startCotRouter);
deleteVehicle _logic;
closeDialog 1;
@@ -0,0 +1,22 @@
#include "..\script_component.hpp"
params ["_logic"];
if (missionNamespace getVariable ["armatak_tcp_socket_is_running", false]) exitWith {
["Socket was called twice", "error", "TCP Socket"] call EFUNC(main,notify);
closeDialog 1;
};
disableSerialization;
["Connecting to TCP Socket", "success", "TCP Socket"] call EFUNC(main,notify);
_tak_server_instance_address = ctrlText 14000;
_tak_server_instance_port = ctrlText 14001;
_tak_server_fulladdress = _tak_server_instance_address + ":" + _tak_server_instance_port;
"armatak" callExtension ["tcp_socket:start", [_tak_server_fulladdress]];
_tak_server_fulladdress call FUNC(startCotRouter);
deleteVehicle _logic;
closeDialog 1;
@@ -0,0 +1,44 @@
#include "..\script_component.hpp"
/*
* Author: Valmo
* Adds a unit into the global marked units array.
*
* Arguments:
* 0: The module logic <OBJECT>
*
* Return Value:
* None
*
* Example:
* [LOGIC] call armatak_server_fnc_routerEntityAdd;
*
* Public: No
*/
params ["_logic"];
if (!local _logic) exitWith {};
private _unit = attachedTo _logic;
switch (false) do {
case (!isNull _unit): {
["Nothing selected", "error", "TCP Socket"] call EFUNC(main,notify);
deleteVehicle _logic;
};
default {
if (_unit in (missionNamespace getVariable ["armatak_server_syncedUnits", []])) exitWith {
["Unit already marked", "warning", "TCP Socket"] call EFUNC(main,notify);
deleteVehicle _logic;
};
GVAR(syncedUnits) = missionNamespace getVariable "armatak_server_syncedUnits";
GVAR(syncedUnits) pushBack _unit;
missionNamespace setVariable ["armatak_server_syncedUnits", GVAR(syncedUnits)];
SETVAR(_unit,GVAR(isRouting),true);
deleteVehicle _logic;
};
};
@@ -0,0 +1,42 @@
#include "..\script_component.hpp"
/*
* Author: Valmo
* Removes a unit from the global marked units array.
*
* Arguments:
* 0: The module logic <OBJECT>
*
* Return Value:
* None
*
* Example:
* [LOGIC] call armatak_server_fnc_routerEntityRemove;
*
* Public: No
*/
params ["_logic"];
if (!local _logic) exitWith {};
private _unit = attachedTo _logic;
deleteVehicle _logic;
switch (false) do {
case (!isNull _unit): {
deleteVehicle _logic;
["Nothing selected", "error", "TCP Socket"] call EFUNC(main,notify);
};
default {
{
if (_x isEqualTo _unit) then {
GVAR(syncedUnits) deleteAt _forEachIndex;
};
} forEach GVAR(syncedUnits);
missionNamespace setVariable ["armatak_server_syncedUnits", GVAR(syncedUnits)];
SETVAR(_unit,GVAR(isRouting),false);
deleteVehicle _logic;
};
};
@@ -0,0 +1,47 @@
#include "..\script_component.hpp"
params [["_server_instance", "", [""]]];
missionNamespace setVariable ["armatak_server_instance", _server_instance];
missionNamespace setVariable ["armatak_tcp_socket_is_running", true];
if (isNil { missionNamespace getVariable "armatak_server_syncedUnits" }) then {
missionNamespace setVariable ["armatak_server_syncedUnits", []];
};
GVAR(syncedUnits) = missionNamespace getVariable "armatak_server_syncedUnits";
[{
GVAR(syncedUnits) = missionNamespace getVariable "armatak_server_syncedUnits";
{
_objectType = _x call BIS_fnc_objectType;
switch (true) do {
case ((_objectType select 0) == "Soldier"): {
_callsign = [_x] call armatak_fnc_extract_unit_callsign;
_group_name = [group _x] call armatak_fnc_extract_group_color;
_group_role = [_x] call armatak_fnc_extract_group_role;
[_x, _callsign, _group_name, _group_role] call armatak_fnc_send_eud_cot;
[_x] call armatak_fnc_send_digital_pointer_cot;
};
case ((_objectType select 0) == "Vehicle"): {
_atak_type = [_x] call armatak_fnc_extract_role;
_callsign = [_x] call armatak_fnc_extract_marker_callsign;
[_x, _atak_type, _callsign] call armatak_fnc_send_marker_cot;
_x call armatak_fnc_extract_sensor_data;
};
case ((_objectType select 0) == "VehicleAutonomous"): {
_atak_type = [_x] call armatak_fnc_extract_role;
_callsign = [_x] call armatak_fnc_extract_marker_callsign;
[_x, _atak_type, _callsign] call armatak_fnc_send_drone_cot;
[_x] call armatak_fnc_send_digital_pointer_cot;
_x call armatak_fnc_extract_sensor_data;
};
};
} forEach GVAR(syncedUnits);
}, 1, []] call CBA_fnc_addPerFrameHandler;
true
+17
View File
@@ -0,0 +1,17 @@
#define COMPONENT server
#define COMPONENT_BEAUTIFIED TCP Socket Client
#include "\armatak\armatak\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS
#ifdef DEBUG_ENABLED_CLIENT
#define DEBUG_MODE_FULL
#endif
#ifdef DEBUG_SETTINGS_CLIENT
#define DEBUG_SETTINGS DEBUG_SETTINGS_CLIENT
#endif
#include "\z\ace\addons\main\script_macros.hpp"
-1
View File
@@ -1 +0,0 @@
/build
-55
View File
@@ -1,55 +0,0 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
}
android {
namespace = "com.armatak.simtak"
compileSdk = 34
defaultConfig {
applicationId = "com.armatak.simtak"
minSdk = 29
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
viewBinding {
enable = true
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
implementation(libs.okhttp)
//Vision - Qr/BarCodeScanner
implementation(libs.play.services.vision)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
-21
View File
@@ -1,21 +0,0 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
@@ -1,24 +0,0 @@
package com.armatak.simtak
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.armatak.simtak", appContext.packageName)
}
}
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"
tools:ignore="ProtectedPermissions" />
</manifest>
-66
View File
@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus"
android:required="false"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/appicon_simtak"
android:usesCleartextTraffic="true"
android:label="@string/app_name"
android:roundIcon="@drawable/appicon_simtak"
android:supportsRtl="true"
android:theme="@style/Theme.SIMTAK"
tools:targetApi="31">
<activity
android:name=".trackerLog.TrackerLogActivity"
android:screenOrientation="portrait"
android:exported="false"
tools:ignore="LockedOrientationActivity" />
<activity
android:name=".ScannerActivity"
android:screenOrientation="portrait"
android:exported="false"
tools:ignore="LockedOrientationActivity" />
<activity
android:name=".HomeActivity"
android:screenOrientation="portrait"
tools:ignore="LockedOrientationActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".LocationSimulationService"
android:exported="true"
android:foregroundServiceType="location"
android:permission="android.permission.ACCESS_MOCK_LOCATION">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</service>
</application>
</manifest>
@@ -1,182 +0,0 @@
package com.armatak.simtak
import android.Manifest
import android.app.Dialog
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.Window
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.armatak.simtak.databinding.ActivityHomeBinding
import com.armatak.simtak.trackerLog.TrackerLogActivity
class HomeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHomeBinding
private var requestCamera: ActivityResultLauncher<String>? = null
private var requestPermissionLauncher: ActivityResultLauncher<String>? = null
private var requested = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHomeBinding.inflate(layoutInflater)
setContentView(binding.root)
enableEdgeToEdge()
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
requestCamera = registerForActivityResult(ActivityResultContracts.RequestPermission()) {
if (it) {
initScan()
} else {
Toast.makeText(
this,
"Sem permissão para acessar a camera. Permita o acesso para continuar",
Toast.LENGTH_LONG
).show()
}
}
requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission(),
) { isGranted: Boolean ->
if (isGranted) {
Toast.makeText(baseContext, "Notificações Habilitadas", Toast.LENGTH_SHORT).show()
requestCamera?.launch(Manifest.permission.CAMERA)
} else {
Toast.makeText(
baseContext,
"Por favor confirme a permissão",
Toast.LENGTH_SHORT
).show()
}
}
initUI()
}
private fun validateUrl() {
val etServerAddressLayout = binding.etServerAddressLayout
val etServerAddress = binding.etServerAddress
val serverAddress = etServerAddress.text.toString()
val regexPatterns = listOf(
"^ws://\\b(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))\\b:[0-9]+\$",
"^ws://([A-Za-z0-9]+(\\.[A-Za-z0-9]+)+)\$"
)
val allowed = regexPatterns.any { patterns ->
Regex(patterns).matches(serverAddress)
}
if(allowed) {
requested = false
val intent = Intent(this, TrackerLogActivity::class.java)
intent.putExtra("webSocketUrl", serverAddress)
startActivity(intent)
} else {
requested = false
etServerAddressLayout.error = "Server Address need to be a valid URL"
}
}
private fun initScan() {
startActivity(Intent(this, ScannerActivity::class.java))
}
private fun initUI() {
binding.btnScanQrCode.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS
) ==
PackageManager.PERMISSION_GRANTED
) {
requestCamera?.launch(Manifest.permission.CAMERA)
} else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
requestNotificationByDialog()
} else {
requestPermissionLauncher?.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}
}
binding.btnConnectToServer.setOnClickListener {
val serverAddress = binding.etServerAddress.text.toString()
if (!requested && serverAddress.isNotBlank()){
validateUrl()
} else {
binding.etServerAddressLayout.error = "This Input cannot be blank"
}
}
configureFooterLinks()
}
private fun requestNotificationByDialog() {
val dialog = Dialog(this)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
dialog.setContentView(R.layout.dialog_alert)
dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
val tvTitle: TextView = dialog.findViewById(R.id.title)
val tvMessage: TextView = dialog.findViewById(R.id.message)
val btnCancel: Button = dialog.findViewById(R.id.btnCancel)
val btnAccept: Button = dialog.findViewById(R.id.btnAccept)
btnCancel.text = getString(R.string.cancel)
btnCancel.setOnClickListener {
dialog.dismiss()
}
tvTitle.text = getString(R.string.allowNotificationsPermission)
tvMessage.text = getString(R.string.needNotificationsPermissionMessage)
btnAccept.text = getString(R.string.goToSettings)
btnAccept.setOnClickListener {
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
intent.putExtra(Settings.EXTRA_APP_PACKAGE, this.packageName)
startActivity(intent)
dialog.dismiss()
}
dialog.show()
}
private fun configureFooterLinks() {
binding.btnGithubProject.setOnClickListener {
openLink(getString(R.string.githubProjectUrl))
}
binding.btnWiki.setOnClickListener {
openLink(getString(R.string.wikiUrl))
}
binding.btnDiscord.setOnClickListener {
openLink(getString(R.string.discordUrl))
}
binding.btnSteamProject.setOnClickListener {
openLink(getString(R.string.steamUrl))
}
}
private fun openLink(url: String) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(intent)
}
}

Some files were not shown because too many files have changed in this diff Show More