Compare commits

...

779 Commits

Author SHA1 Message Date
Pax1601
b42280133c Completed custom weapon wizard modal 2025-10-26 16:34:27 +01:00
Pax1601
94d0b4d10e Merge branch 'release-candidate' into weapon-wizard 2025-10-25 15:17:18 +02:00
Pax1601
057603f926 First implementation of weapon wizard 2025-10-23 18:07:55 +02:00
Pax1601
bfd11c49af Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2025-10-23 18:07:35 +02:00
Pax1601
2a9723b932 Add image overlay import modal and menu option
Introduces ImageOverlayModal for importing image overlays with user-specified corner coordinates. Adds a menu item to trigger the modal and integrates it into the main UI component. Also updates OlNumberInput to support an internalClassName prop for styling flexibility.
2025-10-23 18:06:29 +02:00
Pax1601
f565b9ee6e Add type annotations and key conversions in Map class
Improves type safety by adding explicit type annotations to method parameters and callback functions in the Map class. Updates key handling for object properties to ensure correct types, particularly when interacting with ContextActions, MapOptions, MapHiddenTypes, and destination preview markers.
2025-10-21 17:34:20 +02:00
Pax1601
504c0a0ed9 fix: Map now works with capitalized map names (thanks for creating this need Wirts :P) 2025-10-15 18:50:40 +02:00
Pax1601
c77173f7c9 Enable AAA capability for infantry and fix map layer key case
Set 'canAAA' to true for several infantry units in groundunitdatabase.json, allowing them to engage air targets. Updated map.ts to handle map layer keys in a case-insensitive manner, preventing issues with mismatched key casing.
2025-10-13 22:50:36 +02:00
Pax1601
73af60d91b Updated unit databases and new spawn loadout system 2025-10-12 15:11:55 +02:00
Pax1601
31d7fb6051 Update mist.lua 2025-09-28 12:10:20 +02:00
Pax1601
def15f5565 Merge branch 'python-api' into release-candidate 2025-09-27 18:08:13 +02:00
Pax1601
a257afca4b Add customString and customInteger to Unit data model
Introduced customString and customInteger fields to the Unit class in both backend (C++) and frontend (TypeScript/React). Updated data indexes, interfaces, and API handling to support setting and retrieving these custom fields. Also added UI elements in the unit control menu to display and handle these new properties.
2025-09-27 18:07:37 +02:00
Pax1601
dca8f9189f Merge branch 'python-api' into release-candidate 2025-09-11 21:47:29 +02:00
Pax1601
3eef91fb24 Add cargo weight and draw argument support
Introduces cargo weight and draw argument properties to units across backend, frontend, and Python API. Adds related commands, data extraction, and registration logic, enabling setting and reading of cargo weight and custom draw arguments for units. Includes new API examples and updates to interfaces, data types, and Lua backend for full feature integration.
2025-09-11 21:47:11 +02:00
Pax1601
73a7ea74f3 feat: Added threshold to unit movement 2025-09-09 18:24:53 +02:00
Pax1601
74b446d157 Updated unit database creation files 2025-08-16 17:09:32 +02:00
Pax1601
4e6701ff01 Refactor API callbacks and improve example scripts
Moved register_on_update_callback in api.py for better code organization. Fixed initialization of units_to_delete and corrected simulate_fire_fight usage in example_disembarked_infantry.py. In example_voice_control.py, added cleanup of generated audio files and fixed callback parameter naming for clarity.
2025-08-08 13:14:59 +02:00
Pax1601
5fa1a26843 Add async callbacks and Kronos integration to API
Introduces async callback support for command execution in spawn methods, adds registration/unregistration for update and startup callbacks, and improves logging and signal handling. Adds a new Kronos module and main entry point for initializing and running the API with Kronos integration. Refactors example scripts and updates VSCode launch configurations for new entry points.
2025-08-08 11:06:53 +02:00
Pax1601
151196e5f2 Merge branch 'python-api' into release-candidate 2025-08-08 10:18:01 +02:00
Pax1601
716b0dc48d Refactor unit command methods to use LatLng objects
Updated multiple methods in Unit to accept a LatLng object instead of separate lat/lng floats, improving type safety and consistency. Also made minor improvements and clarifications in the example_disembarked_infantry.py script, and added execution result handling in OlympusCommand.lua for spawned units.
2025-08-08 10:17:46 +02:00
Pax1601
c66c9242b3 Refactor Python API structure and enhance backend command handling
Major refactor of the Python API: moved modules into subdirectories, replaced app.py with api.py, and added new audio and utility modules. Backend C++ code now tracks command execution results, exposes them via the API, and improves command result handling. Also includes updates to the SRS audio handler, random string generation, and VSCode launch configurations.
2025-08-07 17:01:30 +02:00
Pax1601
8404d4d956
Merge pull request #1128 from Rob2816/release-candidate
Added groupID property to dead units
2025-08-07 11:02:19 +02:00
Rob2816
37fa86dce8 Added groupID property to dead units 2025-08-07 10:52:28 +02:00
Pax1601
4bcb5936b4 feat: Add initial API implementation and databases
Introduces a new Python API module with supporting scripts for data extraction, data types, unit management, and utility functions. Adds JSON databases for aircraft, helicopters, ground units, navy units, and mods, as well as configuration and VSCode launch settings. This provides the foundation for interacting with and managing units, spawning, and logging within the application.
2025-08-05 17:26:24 +02:00
Pax1601
4fd9b7e6c2 fix: Development build shown in release version 2025-08-05 11:05:29 +02:00
Pax1601
e4af9b06d3 fix: Ground units spawned in group are on top of each other, no heading when importing units
Units spawned via map, context menu, or unit spawn menu now include a heading property and are offset in latitude to prevent overlap. Also ensures heading is set during import/export. Minor JSX formatting improvements in UnitSpawnMenu.
2025-08-04 20:03:40 +02:00
Pax1601
89bd39cea8 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2025-08-04 19:37:34 +02:00
Pax1601
cd34eebcba fix: ROE not set correctly when setting defaults
Changed the default ROE value in unit.h from OPEN_FIRE_WEAPON_FREE to OPEN_FIRE. Renamed mods.png to image.png in docs/images. Removed an unnecessary blank line in the audio section of olympus.json. Bumped version in version.json from v2.0.3 to v2.0.4.
2025-08-04 19:37:32 +02:00
Pax1601
07060112bc
Merge pull request #1119 from Pax1601/A-4Skyhawk-mods-doc
Example mod files for A-4 Skyhawk
2025-08-02 18:36:44 +02:00
bobprofisker
d6bcbaea7a
Example mod files for A-4 Skyhawk
Example mod files that inlcude A-4 Skyhawk mods.json and mods.lua files that go into
2025-08-02 17:32:28 +01:00
Pax1601
42abb15aaf Merge branch 'main' into release-candidate 2025-08-02 15:15:01 +02:00
Pax1601
dcac0fd4f2 Added missing Iraq map 2025-08-02 15:14:48 +02:00
Pax1601
90d6acb7a4
Update README.md 2025-08-02 14:53:52 +02:00
Pax1601
2c6538663d
Update README.md 2025-08-02 14:52:20 +02:00
Pax1601
280e6ecdd2 Merge branch 'release-candidate' 2025-08-02 13:03:27 +02:00
Pax1601
3ca78d4c7c Final tweaks before release 2025-08-02 12:46:27 +02:00
Pax1601
e7845dd356
Update servermanager.ts 2025-07-29 19:15:59 +02:00
Pax1601
8ef86e75f0
Disconnected page only shown after 10 seconds disconnected 2025-07-29 18:59:02 +02:00
Pax1601
de1f233848
Fixed unarmed ground units not moving 2025-07-29 17:17:15 +02:00
Pax1601
fd72d4ae2d
Merge pull request #1111 from Pax1601/bugfix/wrong-unit-id-type
fix(unit): unit and group id are now of the correct type;
2025-06-02 10:16:59 +02:00
MarcoJayUsai
a112ef4aa2 fix(unit): unit and group id are now of the correct type; added DCS unitId to dead units 2025-05-30 14:01:00 +02:00
Pax1601
71750c43bd
Merge pull request #1108 from Pax1601/1104-add-an-option-to-automatically-show-unit-engagement-range-when-selected
1104 add an option to automatically show unit engagement range when selected
2025-05-18 14:06:51 +02:00
MarcoJayUsai
36a80c8708 refactor: temporary engagement ring color is now the same as fixed one 2025-04-29 13:36:40 +02:00
MarcoJayUsai
600b649449 feat(map): added option to toggle display of temporary engagement rings 2025-04-28 16:22:51 +02:00
MarcoJayUsai
5237dc688a refactor: adding back country, group id and original unit id to the unit data for future uses 2025-04-28 16:14:07 +02:00
Pax1601
2ebf30e23d
Merge pull request #1107 from Pax1601/bugfix/has-sensors-causing-crashes
fix: temporarily removed radarState due to hasSensors() API causing c…
2025-04-21 11:37:02 +02:00
MarcoJayUsai
dc01620b8c fix: temporarily removed radarState due to hasSensors() API causing crashes 2025-04-21 09:32:04 +02:00
MarcoJayUsai
edc3529b67 feature(map): showing ground units engagement rings when selected and no other global rings are selected 2025-04-15 22:20:15 +02:00
Pax1601
13ec455d74 fix: Searchbar threating input as username/password, inability to spawn explosion on marker 2025-04-14 22:14:40 +02:00
Pax1601
8da9249e52
Merge pull request #1106 from Pax1601/feature/navpoints-custom-icons
fix(navpoints): added missing navpoint tag information from lua
2025-04-10 18:04:30 +02:00
MarcoJayUsai
228bb7767e fix(navpoints): added missing navpoint tag information from lua 2025-04-08 22:50:11 +02:00
Pax1601
e6630171cc
Merge pull request #1088 from Pax1601/features/quick-filter-rework-drawings-layers
chore: added expanding tooltip to unit category quick filter buttons
2025-04-05 20:31:36 +02:00
Pax1601
22e37ceec5
Merge branch 'release-candidate' into features/quick-filter-rework-drawings-layers 2025-04-05 20:31:20 +02:00
Pax1601
0ce800d62a
Merge pull request #1097 from Pax1601/bugfix/coalition-drawings
Bugfix/coalition drawings
2025-04-05 20:29:43 +02:00
Pax1601
fa49e455c8
Merge pull request #1098 from Pax1601/feature/navpoints-custom-icons
Feature/navpoints custom icons
2025-04-05 20:29:20 +02:00
Pax1601
3964dafb9e fix: Commander mode not working if AWACS reference coalition different from commanded coalition 2025-04-05 20:27:40 +02:00
MarcoJayUsai
24015686ea feature(navpoints): navpoint marked as TGT have a special icon. Styles reworked. 2025-04-03 14:43:38 +02:00
MarcoJayUsai
77ceae21e1
chore: removed comments 2025-04-03 09:25:52 +02:00
Pax1601
874e01b031 Update audiomanager.ts
fix: Audio menu frequencies list not working, radios reset when changing input/output
2025-04-01 21:04:53 +02:00
MarcoJayUsai
e6ef6cd05b fix(drawings): not initializing empty layers 2025-04-01 15:01:51 +02:00
MarcoJayUsai
ddab28f874 fix(drawings): coalition commanders will not see enemy coalition drawings and navpoints 2025-04-01 14:46:56 +02:00
MarcoJayUsai
2d7db0bf5e chore: added expanding tooltip to unit category quick filter buttons 2025-04-01 12:34:07 +02:00
Pax1601
5d274a3efb chore: Bumped version number 2025-03-31 22:43:27 +02:00
Pax1601
84b3e3dac4 feat: Added more docs to ingame wiki 2025-03-31 22:25:16 +02:00
Davide Passoni
78c655e2f7 feat: Added threat rings to spawn tool 2025-03-31 15:59:27 +02:00
Davide Passoni
de495cc71d feat: added unit ranges on spawn menu 2025-03-31 15:36:38 +02:00
Davide Passoni
c034c19176 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2025-03-31 15:10:05 +02:00
Davide Passoni
7f8d240bed fix: Removed incorrect help string in compact effect spawn menu 2025-03-31 15:09:56 +02:00
Pax1601
624b29ab84
Merge pull request #1084 from Pax1601/features/quick-filter-rework-drawings-layers
refactor(map): unit category quick filter now will reset view by ctrl…
2025-03-31 15:07:23 +02:00
Davide Passoni
e877d9f8e4 fix: added missing fire effect 2025-03-31 15:06:20 +02:00
MarcoJayUsai
43284c46db refactor(map): unit category quick filter now will reset view by ctrl clicking a shown category
Also added the ability to parse drawings sublayer by reading a tag prefixed to drawing name (e.g. [TAGNAME] DrawingName)
2025-03-31 15:05:23 +02:00
Davide Passoni
cf7aa05ec0 feat: Added error message if admin password wrong
Improved looks of admin panel
2025-03-31 12:55:45 +02:00
Davide Passoni
fd2a63c530 fix: Radio menu names being squashed when too long 2025-03-31 12:23:00 +02:00
Davide Passoni
266326c40c fix: Added callback to close all tooltips on click 2025-03-31 11:29:00 +02:00
Davide Passoni
1bca2e5c26 fix: "Follow roads" toggle available for navy units 2025-03-31 11:14:06 +02:00
Pax1601
64e4e7f301
Merge pull request #1083 from Pax1601/airborne
Airborne
2025-03-31 11:07:20 +02:00
Davide Passoni
2d0e10bc0b fix: not airborne units no longer targeted, racetracks not drawn for airborne units 2025-03-31 11:06:57 +02:00
Pax1601
1248ffb60b feat: added airborne variable 2025-03-31 08:14:17 +02:00
Pax1601
825d60e754
Merge pull request #1073 from Pax1601/drawings-refinements
Drawings refinements
2025-03-30 10:34:50 +02:00
Pax1601
f392b08392
Merge pull request #1075 from Pax1601/1074-qol-unit-type-exclusive-filter
1074 qol unit type exclusive filter
2025-03-30 10:33:46 +02:00
Pax1601
aee1f21cd6
Merge pull request #1077 from Pax1601/1076-qol-add-selected-map-source-to-session-data
feat(map): session data is now saving selected map source
2025-03-30 10:33:04 +02:00
MarcoJayUsai
c1aadece29 feat(map): session data is now saving selected map source 2025-03-29 11:33:01 +01:00
MarcoJayUsai
fbc598e3aa fix(coordinates): MGRS are now separed properly 2025-03-28 22:21:03 +01:00
MarcoJayUsai
b600b2503b fix(state buttons): state buttons hovering styles will be applied instantly 2025-03-28 20:11:35 +01:00
MarcoJayUsai
011ccc0a99 feature(map): added ability to exclusively show unit types 2025-03-28 19:47:40 +01:00
MarcoJayUsai
3814052fd9 feat(navpoints): added header button to quick toggle navpoints drawing 2025-03-28 19:21:59 +01:00
MarcoJayUsai
0558227ce6 refactor(drawings): reduced the zoom of the go to drawing feature 2025-03-28 19:16:09 +01:00
Davide Passoni
0452a8081b feat: Added material to quick reference guide 2025-03-28 17:07:38 +01:00
Davide Passoni
bdf9c83053 feat: Added starred spawns to spawn menu and ability to remove starred spawns 2025-03-27 17:10:27 +01:00
Davide Passoni
3c02802807 feat: Added selection tools to unit list in unit control menu 2025-03-27 16:22:25 +01:00
Davide Passoni
ffddb9cd1e fix: Removed accidental development feature in unit spawn men
Also bumped version to 2.0.1
2025-03-27 15:46:32 +01:00
Davide Passoni
55f75ff149 feat: added nightly link to manager to update without github account
added ability to force beta version
2025-03-27 13:27:50 +01:00
Davide Passoni
c9b143b5e0 feat: Multiple improvements to audio backend 2025-03-27 13:16:39 +01:00
Pax1601
9cbfa2a8aa
Merge pull request #1072 from Pax1601/1054-drawings-control-panel-separate-global-mission-drawings-control-from-navpoints-control
1054 drawings control panel separate global mission drawings control from navpoints control
2025-03-26 16:48:39 +01:00
MarcoJayUsai
3635837495 Merge remote-tracking branch 'origin/release-candidate' into 1054-drawings-control-panel-separate-global-mission-drawings-control-from-navpoints-control 2025-03-26 16:17:29 +01:00
MarcoJayUsai
3f1fde2398 feature(drawings): searched drawings (or navpoints) container will auto open if containing a match 2025-03-26 16:13:58 +01:00
Pax1601
c2489d638a
Merge pull request #1071 from Pax1601/1053-drawings-control-panel-make-shown-hidden-states-more-obvious
refactor(drawings): changed styles for visible / hidden drawing layers
2025-03-26 16:06:22 +01:00
Davide Passoni
0d246c7c25 feat: Added ability to change command mode, improved local connection detection 2025-03-26 16:05:06 +01:00
MarcoJayUsai
1db8736391 fix(drawings): drawings filtering utility made case insensitive 2025-03-26 15:58:07 +01:00
MarcoJayUsai
3067100562 feature(drawings): added drawings filtering by string and go to drawing feature 2025-03-26 15:51:36 +01:00
MarcoJayUsai
fca63fb103 feature(drawings): Navpoints settings saved in session data 2025-03-26 15:21:17 +01:00
MarcoJayUsai
1262c85802 feature(drawings): Navpoints separated from Drawings
Known issue: navpoints settings are not saved in session, to be fixed.
2025-03-26 14:30:24 +01:00
MarcoJayUsai
d0f5be7269 refactor(drawings): changed styles for visible / hidden drawing layers 2025-03-26 14:01:48 +01:00
Davide Passoni
4062e69661 fix: Incorrect "Development build" string in header 2025-03-26 12:24:19 +01:00
Davide Passoni
bb0ded2b46 fix: "Don't show again" tickbox not being respected 2025-03-26 12:15:28 +01:00
Davide Passoni
49990e01ee fix: Fixed manager not respecting autoconnectwhentrue and srsport settings 2025-03-26 11:40:02 +01:00
Davide Passoni
3d61b7e1a7 Fix: aligned airbase spawn menu to other menus 2025-03-26 10:33:11 +01:00
Davide Passoni
7ae15239b1 fix: Context menu shown when dragging handles 2025-03-26 10:24:46 +01:00
Davide Passoni
589479ba56 fix: Aligned tanker orbit behaviour 2025-03-26 10:15:10 +01:00
Davide Passoni
40aa6fcfdc fix: Quick box selection causes units to be immediately deselected 2025-03-26 09:48:12 +01:00
Pax1601
41b4328eaf fix: Unable to clone units if game master with spawn restrictions on
Other minor graphical fixes
2025-03-25 19:30:00 +01:00
Pax1601
bc65bf546f feat: added support for callsigns 2025-03-25 13:05:40 +01:00
Pax1601
f91daed25e fix: Missing options in preferences causing inconsistent states 2025-03-25 11:51:05 +01:00
Pax1601
a1f6a50a46 fix: Added favicon 2025-03-25 11:44:06 +01:00
Pax1601
8a9c319e45 fix: Scenic state toggles not being respected 2025-03-25 11:41:05 +01:00
Pax1601
8e55051410 fix: Unit targets not being shown 2025-03-25 09:58:37 +01:00
Pax1601
b20134f8f1 fix: sessionData not being saved after mission reload 2025-03-25 09:37:55 +01:00
Pax1601
6af6545f09 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2025-03-24 23:03:40 +01:00
Pax1601
9fc1519ef6 fix: Improved audio quality of radio 2025-03-24 23:03:28 +01:00
Pax1601
039c922649
Merge pull request #1043 from Pax1601/features/redgreen-unit
Features/redgreen unit
2025-03-24 23:02:20 +01:00
Pax1601
70b6143fd9 Merge branch 'release-candidate' into features/redgreen-unit 2025-03-24 23:02:04 +01:00
Pax1601
8cce77c4d3 fix: Complete implementation of alarm state 2025-03-24 22:59:41 +01:00
Pax1601
7573720398 fix: Minor fix on commented debug string 2025-03-24 21:17:41 +01:00
Pax1601
2b5b428237 fix: Added setting of forced AlarmState 2025-03-24 21:07:08 +01:00
MarcoJayUsai
1622d663bb feat(alarm state): refactor to separe alarm state from radar state. Kown issue: alarm state is not correctly mantained 2025-03-24 18:42:04 +01:00
Davide Passoni
eff96ce0c2 feat: Control scheme improvement 2025-03-24 16:55:40 +01:00
Pax1601
0b8fb969b2 fix: Added option to upload hidden files 2025-03-23 16:50:34 +01:00
Pax1601
c66086d64f fix: missing else in mod units code 2025-03-23 16:06:38 +01:00
Pax1601
8eaebb5d22 chore: updated setup-node action 2025-03-23 15:40:48 +01:00
Pax1601
c33afa5215 fix: Humans can be exploded 2025-03-22 19:27:41 +01:00
Pax1601
3e19c84c8e
Merge pull request #1044 from Pax1601/features/DDM-coordinates
feat(coordinates): added DDM format
2025-03-22 19:09:27 +01:00
Pax1601
3b075ec276 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2025-03-22 19:03:05 +01:00
Pax1601
2fd8752050 feat: better handling of mods payloads 2025-03-22 19:03:02 +01:00
MarcoJayUsai
45f828c838 feat(map): added coordinates copy feature 2025-03-22 12:33:34 +01:00
MarcoJayUsai
d35e6063e7 feat(coordinates): added DDM format 2025-03-22 10:21:08 +01:00
MarcoJayUsai
f7e9fc5cbc Merge branch 'release-candidate' into features/redgreen-unit 2025-03-22 09:18:16 +01:00
MarcoJayUsai
b7bf89ce2f chore: removed useless code 2025-03-22 09:15:48 +01:00
MarcoJayUsai
a733c98259 refactor: removed unused code 2025-03-22 09:12:53 +01:00
MarcoJayUsai
efd7c3cec9 chore: removed comments 2025-03-22 09:10:53 +01:00
Davide Passoni
7155429dc7 fix: Added databases copy step in build scripts 2025-03-21 17:40:25 +01:00
Davide Passoni
326fbff982 fix: Incorrect representation of some ground unit markers 2025-03-21 17:12:20 +01:00
MarcoJayUsai
3a44608e2b Merge remote-tracking branch 'origin/release-candidate' into features/redgreen-unit 2025-03-21 16:47:47 +01:00
MarcoJayUsai
f1fcabe7f7 feat(alarm state): alarm state command is now working in DCS 2025-03-21 16:21:35 +01:00
Davide Passoni
3ab10af98b feat: Added unit clustering and other small performance and loadtime improvements 2025-03-21 16:11:57 +01:00
MarcoJayUsai
2a00bab149 feat(alarm state): added unit control panel buttons (WIP) 2025-03-21 12:33:15 +01:00
Pax1601
99e742498d fix: error in spawn menu, fixed smoke not working 2025-03-20 19:30:40 +01:00
Davide Passoni
b3e53d07dd fix: Added missing commander restrictions 2025-03-20 17:30:28 +01:00
Davide Passoni
69e8fed623 fix: Scenic AAA not stopping when target out of range 2025-03-20 16:53:23 +01:00
Davide Passoni
0765459cfd feat: Added wiki modes to audio, drawing and gamemaster menus.
Feat: improved looks of gamemaster menu
2025-03-20 16:51:58 +01:00
Davide Passoni
791b1fc4ab fix: Login modal rendered twice
Also added ability to login by username or by role
2025-03-20 10:49:07 +01:00
Davide Passoni
0ef5de51c4 fix: Drawings visibility not aligned with map option 2025-03-19 17:39:59 +01:00
Davide Passoni
2d26862b6c fix: Error in admin panel inputs fixed, plus improvements to modal panels 2025-03-19 17:23:17 +01:00
Davide Passoni
f058958c13 fix: Coalition of unit bullseye info toggle now working 2025-03-19 16:33:10 +01:00
Davide Passoni
48d64078d8 fix: fixed wiki mode for small screens 2025-03-19 16:23:27 +01:00
MarcoJayUsai
18960ca51e feat(radar state): radar state is now being read from DCS and displayed as a dot (subject to change) 2025-03-19 14:36:40 +01:00
Davide Passoni
4350cd93e5 fix: Minor package updates
Possible breaking change for Vite, to be monitored
2025-03-19 12:59:00 +01:00
Pax1601
3c33d3883e fix: Small fixes to responsive design 2025-03-18 16:14:39 +01:00
MarcoJayUsai
ee15106be1 feat(radar state): initial scaffolding 2025-03-18 14:42:46 +01:00
Pax1601
50f3882b3e fix: "Alt" keybinds getting stuck when switching windows with alt+tab 2025-03-18 13:02:12 +01:00
Pax1601
cf86c4ade9 fix: minor improvements to miss on purpose mode 2025-03-18 12:53:22 +01:00
Pax1601
ddf9883f89 fix: Reverted some changes to miss on purpose mode 2025-03-18 11:05:33 +01:00
Pax1601
8ffcbaa05b Merge branch 'laser-fix' into release-candidate 2025-03-18 11:00:10 +01:00
Pax1601
dd2856a993 fix: Laser and infrared correctly removed 2025-03-18 10:58:35 +01:00
Davide Passoni
c44caa9cea feat: small change to flak mode miss on purpose 2025-03-17 16:54:33 +01:00
Pax1601
3aafa26c70 feat: New predicting algorithm 2025-03-16 22:33:28 +01:00
Pax1601
e2ac37ef18 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2025-03-14 18:43:25 +01:00
Pax1601
3d33319a19 fix: minor changes to databases 2025-03-14 18:43:10 +01:00
Davide Passoni
83e3c8b681 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2025-03-14 16:46:19 +01:00
Davide Passoni
f0826bbdba fix: Fixed multiple errors in scenic AAA modes 2025-03-14 16:45:46 +01:00
Pax1601
6d5eb05f0b Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2025-03-13 20:50:55 +01:00
Pax1601
f77b008701 feat: Updated database for flak 2025-03-13 20:50:51 +01:00
Davide Passoni
5acc0e8ac5 fix: Audio backend working if both port and endpoint added
Added ability to use uri for backend address (remote debugging)
2025-03-13 16:54:16 +01:00
Davide Passoni
760fe18cc7 fix: Autoconnect when local checkbox not reflecting configuration 2025-03-13 09:39:34 +01:00
Pax1601
34f9a8bc40 feat: Improvements on scenic modes 2025-03-12 18:43:14 +01:00
Davide Passoni
23f9eee39f fix: Fixed error in SRS coalition 2025-03-11 16:28:26 +01:00
Davide Passoni
46f2ff4403 feat: added proxyHeader and comments to config file 2025-03-11 16:25:16 +01:00
Davide Passoni
386d5298a2 feat: added admin password and admin modal 2025-03-10 17:16:02 +01:00
Davide Passoni
9a7af84cd4 feat: databases handled by Olympus, only mods database is under user control 2025-03-07 17:16:06 +01:00
Davide Passoni
403280aa22 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2025-03-07 16:39:36 +01:00
Davide Passoni
d90ef540f9 fix: added compatibility checks with v1.0.4 2025-03-07 16:39:33 +01:00
Davide Passoni
f1fb3073d2 Update settings.ejs 2025-03-07 16:14:45 +01:00
Davide Passoni
be879e3660 feat: added ability to change and check SRS port in manager 2025-03-07 16:14:42 +01:00
Pax1601
e9112e5be6
Merge pull request #1014 from Pax1601/features/navpoints
Features/navpoints
2025-03-07 14:48:18 +01:00
Davide Passoni
42cfb36c04 Added checkbox for autoconnection when local 2025-03-07 14:45:01 +01:00
MarcoJayUsai
6e7b5b1cc3 feat(navpoints): added navpoint sublayers 2025-03-07 12:36:10 +01:00
MarcoJayUsai
8e20499b92 feat(drawings): added navpoints 2025-03-07 12:00:43 +01:00
Davide Passoni
16e77087f5 fix: Removed unnecessary entries from sidebar and header, fixed non working main menu links 2025-03-07 11:12:17 +01:00
Davide Passoni
eed91e8486 fix: Update old version of workflow package 2025-03-07 09:42:56 +01:00
Davide Passoni
016c2d45f6 Merge branch 'v2' into release-candidate 2025-03-07 09:29:23 +01:00
Davide Passoni
0a5a507f70 Merge branch 'v2' of https://github.com/Pax1601/DCSOlympus into v2 2025-03-06 17:45:31 +01:00
Davide Passoni
8406619868 feat: started working on wiki entries and tooltips, minor fixes and improvements to presentation 2025-03-06 17:45:20 +01:00
MarcoJayUsai
3142a438f7 fix(drawings): added keys to drawing menu elements 2025-03-06 17:14:05 +01:00
MarcoJayUsai
94fe8488e4 refactor(drawings): added global drawing lines thickness normalization 2025-02-28 14:33:31 +01:00
Davide Passoni
8aac6b7d7e feat: Aligned orbits representation, added visibility option 2025-02-26 12:05:59 +01:00
Davide Passoni
c7ff73f8a6 fix: Saving in progress spinner pushing load/export buttons right 2025-02-26 10:49:48 +01:00
Davide Passoni
2ab072c929 fix: Dropdowns getting reset periodically 2025-02-26 10:46:57 +01:00
Davide Passoni
d4a06e9edb Fixed measure bug, added middle mouse click shortcut 2025-02-26 10:39:08 +01:00
Davide Passoni
b2477112b1 Completed first iteration of drawings management on v2 2025-02-26 09:39:30 +01:00
Davide Passoni
1a93ee68d0 fix: Check for protected units not working for control panel 2025-02-06 17:31:27 +01:00
Davide Passoni
1deeaacf1d feat: added grouped path markers
fix: fixed shortcuts getting stuck
2025-02-06 16:28:23 +01:00
Davide Passoni
52606b8d57 feat: completed measure handling 2025-02-03 17:27:19 +01:00
Davide Passoni
627c4b5584 feat: started working at measuring tool 2025-01-31 17:25:14 +01:00
Davide Passoni
a65a5a5bed fix: Groups emptied correctly when all units are killed 2025-01-31 16:16:56 +01:00
Davide Passoni
4f927faeb4 fix: Fixed wrong server code activation 2025-01-30 16:23:19 +01:00
Davide Passoni
9525982161 feat: added laser code change, target move, and delete
Note: deleted lasers are not removed from table and keep being drawn. Also added a cooler looking server page
2025-01-30 16:20:31 +01:00
Davide Passoni
cc902aec04 feat: started adding editable laser/infrared 2025-01-29 17:25:09 +01:00
Davide Passoni
74e2332b17 fix: fixed error in credentials management 2025-01-29 11:13:55 +01:00
Pax1601
5a4a202805 feat: started implementing infrared and laser 2025-01-29 08:03:32 +01:00
Davide Passoni
79f9905413 feat: completed orbit management 2025-01-28 09:47:44 +01:00
Davide Passoni
c2ea746d48 feat: started adding ability to set and draw racetracks 2025-01-24 17:33:27 +01:00
Davide Passoni
96415fd087 Feat: added backend ability to set spawn heading 2025-01-24 15:01:25 +01:00
Davide Passoni
d1d4116e66 feat: Added unit spawn heading selection 2025-01-24 10:55:57 +01:00
Davide Passoni
6074367300 fix: better color management of unit markers 2025-01-23 12:54:20 +01:00
Davide Passoni
b711872d6c feat: Added indicator for "operate as" units 2025-01-23 12:01:38 +01:00
Davide Passoni
20db9647bd fix: Toolbar button color different when hovering and selected 2025-01-23 10:58:11 +01:00
Davide Passoni
d31aa30da8 feat: added coalition selection for audio manager 2025-01-22 12:53:48 +01:00
Davide Passoni
cde33fdd76 fix: Spawn effect menu uses same logic as unit spawn, fixed airbase spawn menu 2025-01-22 11:21:42 +01:00
Davide Passoni
1374f270eb Feat: text to speech source controls PTT of connected sinks 2025-01-20 17:24:50 +01:00
Davide Passoni
77a7397f1c fix: added missing setting of volume to node 2025-01-20 17:15:49 +01:00
Davide Passoni
e6a564ff61 feat: added volume slider for radios 2025-01-20 17:09:37 +01:00
Davide Passoni
6e5e1914ec feat: Added advanced settings menu 2025-01-20 17:01:44 +01:00
Davide Passoni
5b6f58a38e feat: completed formation menu 2025-01-20 15:07:58 +01:00
Davide Passoni
9bd206a750 Added warning modals 2025-01-13 15:11:49 +01:00
Davide Passoni
0c391df69f feat: added missing carriers data 2025-01-13 11:31:40 +01:00
Davide Passoni
711f6094f0 feat: Improved formation menu 2025-01-13 09:36:43 +01:00
Davide Passoni
0376d020e7 feat: Implemented import/export page 2025-01-07 15:36:36 +01:00
Davide Passoni
c9c34f013f fix: hotgroup button updated when unit dies 2024-12-20 16:21:35 +01:00
Davide Passoni
5797b9d209 feat: added starred spawns to session data 2024-12-20 15:43:54 +01:00
Davide Passoni
71e47bce0b feat: Unit hotgroups saved to sessiondata 2024-12-19 15:43:27 +01:00
Davide Passoni
1c86ba1d4c feat: Drawings added to sessiondata 2024-12-19 14:50:12 +01:00
Davide Passoni
ffeecfbf9e feat: Created coalitionareamanager, fixed areas creation and management 2024-12-18 17:50:11 +01:00
Davide Passoni
416f0d3e36 fix: solved breaking error on production with draggable paths in leaflet 2024-12-18 14:22:19 +01:00
Davide Passoni
2bbcbc5576 feat: added simple radio effect and left/right panner 2024-12-17 18:51:30 +01:00
Davide Passoni
dbd87d5724 Fix: temporary fix for srtm error 2024-12-17 16:06:06 +01:00
Davide Passoni
17cd42a1a0 chore: cleanup of dependencies 2024-12-17 15:38:13 +01:00
Pax1601
182fe294de
Merge pull request #995 from Pax1601/features/v1/unit-coordinates-copy
feat(map): unit coordinates are now copied entirely. Added info poup.
2024-12-17 15:18:34 +01:00
Davide Passoni
c2d5d4ea17 feat: Implemented server mode 2024-12-16 17:24:02 +01:00
MarcoJayUsai
95db9b5d38 feat(map): unit coordinates are now copied entirely. Added info poup. 2024-12-13 15:15:23 +01:00
Davide Passoni
032b74b57b feat: better toolbar descriptions 2024-12-12 17:06:28 +01:00
Davide Passoni
f84b560351 fix: map sources not being loaded correctly in static version 2024-12-12 16:56:11 +01:00
Davide Passoni
8006d639ae fix: magvar used for BE calls
fix: unit summary labels
2024-12-12 16:43:24 +01:00
Davide Passoni
89abcb3330 fix: breaking change with new node version 2024-12-12 15:02:25 +01:00
Davide Passoni
8208316fb9 chore: switch to google cloud text to speech 2024-12-12 14:36:14 +01:00
Davide Passoni
6250f760a9 chore: updated dependencies of server 2024-12-12 13:27:35 +01:00
Davide Passoni
d7edb00254 Merge branch '961-hotkeys-get-stuck' into v2 2024-12-11 18:21:47 +01:00
Davide Passoni
e6d2d906e1 fix: flashing spawn context menu 2024-12-11 18:20:13 +01:00
Pax1601
76efe84be6
Merge pull request #985 from Pax1601/961-hotkeys-get-stuck
961 hotkeys get stuck
2024-12-11 18:08:14 +01:00
Davide Passoni
7fe9b0d19f fix: buttons and actions no longer getting stuck
fix: context menu resizes if accordion is opened
feat: added expanding descriptions for context actions
2024-12-11 18:06:59 +01:00
Davide Passoni
e9896963ca Merge branch 'v2' into 961-hotkeys-get-stuck 2024-12-11 14:38:38 +01:00
Davide Passoni
da2152f0e3 fix: I have a good feeling for relative imports this time 2024-12-11 10:37:19 +01:00
Davide Passoni
dc7fd2c870 fix: will I ever make relative paths work? 2024-12-11 10:22:53 +01:00
Pax1601
e41d3c93a6 fix: error in code for audiomanager address 2024-12-10 20:44:20 +01:00
Pax1601
7684461edb Merge branch 'v2' of https://github.com/Pax1601/DCSOlympus into v2 2024-12-10 20:42:32 +01:00
Pax1601
c618a36072 fix: wrong audio address 2024-12-10 20:40:47 +01:00
Davide Passoni
dd7e34178a chore: more trials for relative image paths 2024-12-10 17:48:34 +01:00
Davide Passoni
95505ec9fa chore: fixed images relative imports for static build 2024-12-10 17:42:57 +01:00
Pax1601
8d7aa5df65
Merge pull request #972 from Pax1601/966-implement-toolbar-and-add-copypaste-as-context-actions
feat: implemented map toolbar
2024-12-10 16:59:26 +01:00
Davide Passoni
8f00e8a9e2 feat: implemented map toolbar 2024-12-10 16:58:51 +01:00
Davide Passoni
ce129691a7 chore: Removed temporary audio backend address 2024-12-09 15:32:04 +01:00
Pax1601
3d204af60f
Merge pull request #965 from Pax1601/962-show-action-specific-cursor-when-action-is-active
962 show action specific cursor when action is active
2024-12-09 14:11:30 +01:00
Davide Passoni
00d7b451ec feat: added specific cursors for different context actions and spawns 2024-12-09 14:10:34 +01:00
Davide Passoni
96899121f7 chore: switched all urls to relative paths 2024-12-09 10:18:58 +01:00
Pax1601
a4452aee94 fix: Units are spawned at 0,0 2024-12-07 16:34:00 +01:00
Pax1601
f80321a267 fix: wrong path for units silhouettes 2024-12-07 10:27:36 +01:00
Pax1601
2391977082 fix: wrong images path for units 2024-12-07 10:25:28 +01:00
Pax1601
7a0504227b fix: changed images path to relative 2024-12-07 10:23:04 +01:00
Davide Passoni
4278c6fa9a fix: More missing files commit 2024-12-06 18:02:07 +01:00
Davide Passoni
db4e9870b0 fix: Missing file commit 2024-12-06 18:01:38 +01:00
Davide Passoni
be439be264 feat: updated index position 2024-12-06 17:59:09 +01:00
Davide Passoni
1f60f51898 feat: Moved base vite location 2024-12-06 17:57:09 +01:00
Davide Passoni
a899c5ffca feat: setup app for static compilation
Breaking change!: initDraggablePath disabled because it breaks the app
2024-12-06 17:47:08 +01:00
Davide Passoni
ffade5fb8e (fix): More general address calculation 2024-12-06 17:09:57 +01:00
Davide Passoni
b57d6b305a fix: Default users can be used again 2024-12-06 16:22:02 +01:00
Davide Passoni
786729c006 fix: Login prompt crashing app 2024-12-06 15:25:40 +01:00
Davide Passoni
258d21672c feat: Added custom authentication headers support
bugfix: Fixed incorrect saving of quick access spawn
refactor: Removed compactunitspawnmenu and condensed in single unitspawnmenu class to reuse code
2024-12-05 19:37:38 +01:00
Pax1601
c11a9728e8 Minor fix 2024-12-03 20:34:31 +01:00
Pax1601
c8da3e6da3 Added check on audio interval 2024-12-03 20:14:16 +01:00
Pax1601
f17ee42d63 Implemented session data for audio 2024-12-03 18:54:30 +01:00
Davide Passoni
5e40d7abf1 Started work on persistent session data 2024-12-01 12:40:07 +01:00
Pax1601
42e62be0f5 Started google cloud tests 2024-11-28 20:08:43 +01:00
Davide Passoni
dd641fc2aa Initial tests on sppech synthesis 2024-11-28 17:49:09 +01:00
Davide Passoni
8580c5c62b Fixed error in profiles reset 2024-11-27 17:48:34 +01:00
Davide Passoni
b4841872ca More work on AWACS mode 2024-11-27 17:36:32 +01:00
Davide Passoni
a92d4403d7 Merge branch 'v2' of https://github.com/Pax1601/DCSOlympus into v2 2024-11-27 11:28:33 +01:00
Davide Passoni
8cd18eb921 Adding AWACS graphical mode 2024-11-27 11:28:30 +01:00
Pax1601
8bcf564f07 Merge branch 'v2' of https://github.com/Pax1601/DCSOlympus into v2 2024-11-27 08:10:18 +01:00
Pax1601
264c381bc3 Started automatic AWACS call generation 2024-11-27 08:10:06 +01:00
Davide Passoni
7813f8335a WIP disabled awacs tools 2024-11-25 15:15:54 +01:00
Pax1601
a6e28e9064
Merge pull request #948 from Pax1601/bugfix/v1/wrong-unit-on-reconnection
Bugfix/v1/wrong unit on reconnection
2024-11-25 10:17:14 +01:00
Davide Passoni
1791eaa37d Started adding AWACS panel 2024-11-23 17:18:16 +01:00
Pax1601
116d4fa894
Merge pull request #949 from Pax1601/feature/v1/selected-unit-coords
Feature/v1/selected unit coords
2024-11-23 17:05:29 +01:00
MarcoJayUsai
8b5df691ec
fix(selected unit coords): failsafe in case of absence of the navigator element 2024-11-22 15:14:57 +01:00
MarcoJayUsai
f00fce7fe7
fix(selected unit coords): added minutes indication in latlngdec coordinates format
In the coordinates panel, a lat lng with decimal minutes would appear without the ending " ' " character.
2024-11-22 15:10:44 +01:00
Davide Passoni
897afb2fef Multiple bugfixes 2024-11-22 14:56:26 +01:00
Pax1601
5c3960868a Update coordinatespanel.tsx 2024-11-21 21:23:38 +01:00
Pax1601
376a63b363 Minor radio panel changes 2024-11-21 20:55:28 +01:00
Davide Passoni
402a1457aa Major controls rework 2024-11-21 17:35:51 +01:00
MarcoJayUsai
6bb150a41c feat(map): added selected air units FL in unit coordinates panel; added new coordinates system 2024-11-20 12:50:56 +01:00
MarcoJayUsai
2cadebcabd feat(map): click selected unit coordinates panel will now change location system 2024-11-20 11:43:10 +01:00
MarcoJayUsai
b61289d996 fix(mouseinfopanel): switched to right mouse button to copy coordinates, added tip 2024-11-20 11:27:40 +01:00
Pax1601
73c8ce2fe7 Minor bugfixes 2024-11-20 08:09:00 +01:00
Davide Passoni
38f6788fa8 Added spawn context menu and controls rework 2024-11-19 17:45:46 +01:00
MarcoJayUsai
89051c3e85 refactor(unit): moved data update code from initialize to update; made initialize and update final 2024-11-19 13:58:16 +01:00
MarcoJayUsai
064c24e023 fix(map): reconnecting players will not be displayed with wrong name or wrong coalition 2024-11-18 21:56:01 +01:00
MarcoJayUsai
e273203629 feat(map): selected unit coordinates panel moved to top; coords are now copy-able 2024-11-16 18:33:59 +01:00
Pax1601
430d8db15d Tweaked kiowa short label 2024-11-16 11:20:09 +01:00
Pax1601
f1eae9685f Minor changes to short labels 2024-11-16 11:18:48 +01:00
Pax1601
17c71eb4ed Updated database with Chinook 2024-11-16 11:16:52 +01:00
Pax1601
4bbe5eb2f8 Possibly fixed unreadable radio when transmitting on two frequencies 2024-11-15 09:08:54 +01:00
Davide Passoni
c8e1f76b38 Fixed IADS creation and added livery/skill selection for units 2024-11-14 17:23:16 +01:00
Davide Passoni
fa215142ad Fixed radios not working, added mouse coordinates panel, started readding tips 2024-11-13 17:13:30 +01:00
Pax1601
17b10bebd5
Merge pull request #943 from Pax1601/feature/human-original-callsign
feat(map): added an option to show human controlled unit original callsign
2024-11-13 09:33:51 +01:00
Pax1601
b97713f8cc Fixed error in express address 2024-11-12 16:56:51 +01:00
Pax1601
53237c6197 Added different address for express backend 2024-11-12 16:50:01 +01:00
Pax1601
9d225bfc1a Added starred spawns 2024-11-12 16:35:01 +01:00
MarcoJayUsai
5e5ee30b8f feat(mouse info panel): added selected unit coordinates displaying
The coordinates are only shown if one unit has been selected.
2024-11-11 18:56:29 +01:00
Davide Passoni
68980651dc Added keybinding menu and server side profiles 2024-11-11 17:07:12 +01:00
MarcoJayUsai
5cd566c7ca feat(map): added an option to show human controlled unit original callsign 2024-11-11 12:19:05 +01:00
Pax1601
62af0f74e7 Readded camera plugin, hotgroups, fixed smoke spawning 2024-11-10 12:27:01 +01:00
Pax1601
fc8b0d9f7a
Merge pull request #939 from NimbusPulse/fix/frontend-path-traversal
Frontend: Fix possible path traversal
2024-11-10 09:14:49 +01:00
Pax1601
95e18f6503 Added hotkeys 2024-11-09 18:22:21 +01:00
Pax1601
c2b0849fb6 Added default categories to databases 2024-11-08 20:43:09 +01:00
Pax1601
a89861128c Fixed missing category error 2024-11-08 20:42:31 +01:00
Pax1601
4e84a97367 Added ability to rotate movement path 2024-11-08 19:55:37 +01:00
Davide Passoni
644404c4e6 Readded context menus 2024-11-08 17:04:01 +01:00
Davide Passoni
df939f1ac3 Readded command mode options 2024-11-07 17:39:34 +01:00
Davide Passoni
454c7ad2de Merge branch 'refactoring' of https://github.com/Pax1601/DCSOlympus into refactoring 2024-11-07 10:05:32 +01:00
Davide Passoni
bf7115288b More work adding back missing functions 2024-11-07 10:05:27 +01:00
Pax1601
2530d6dd78 Reimplemented changes before merge 2024-11-06 20:12:41 +01:00
Davide Passoni
6d551c51eb Merge branch 'refactoring' of https://github.com/Pax1601/DCSOlympus into refactoring 2024-11-06 17:33:01 +01:00
Davide Passoni
636803b2ac Large rework of events and state 2024-11-06 17:32:31 +01:00
Pax1601
475b04eff7 Completed adding events 2024-10-29 07:54:58 +01:00
Pax1601
7f5873b5b8 More refactoring of events 2024-10-28 07:53:09 +01:00
Davide Passoni
14c0a2f1e8 Refactored app state 2024-10-21 19:02:33 +02:00
Pax1601
4946807d88 Switched to using constants for colors 2024-10-20 17:01:28 +02:00
Pax1601
7fa39561e3 Multiple small improvements and bugfixes 2024-10-19 10:53:43 +02:00
Davide Passoni
0c5139f5ee Started working on JTAC tools 2024-10-18 20:17:04 +02:00
Pax1601
58f114bba0 Changed shape of distance volume curve 2024-10-15 21:01:22 +02:00
Davide Passoni
065cdf3648 Completed the audio panel 2024-10-15 17:40:39 +02:00
Timm Ortloff
03bd14d3fe databases.js: Fix possible path traversal 2024-10-15 04:20:50 +02:00
Pax1601
6cc1572b11 More tests 2024-10-12 18:34:20 +02:00
Davide Passoni
4947997a0c Added explosions, protection screen and delete unit 2024-10-12 17:13:41 +02:00
Pax1601
44bd054a3d
Merge pull request #938 from Pax1601/follow-tool
Follow tool
2024-10-10 14:35:50 +02:00
Davide Passoni
b13689c09a Completed formation tool 2024-10-10 14:35:14 +02:00
Pax1601
e11f4a6c11 Started adding scale sliders 2024-10-10 07:52:33 +02:00
Pax1601
12b9337026 Added limiter to peak meter 2024-10-09 18:41:40 +02:00
Davide Passoni
10a76c47ff Added custom formation tool 2024-10-09 18:30:13 +02:00
Pax1601
b282e5d676 Added handling of urls for audio manager address 2024-10-08 14:29:59 +02:00
Pax1601
ef48147322 Added port read 2024-10-08 14:27:25 +02:00
Pax1601
804743c051 Moved audio sink toggle to unit control panel 2024-10-08 13:59:07 +02:00
Pax1601
84a1375663 Removed unused website folder 2024-10-08 08:32:30 +02:00
Pax1601
88cf20a4d9 Small bugfixes from preview on server 2024-10-08 08:30:26 +02:00
Pax1601
0003363d71
Merge pull request #937 from Pax1601/srs-integration
Added packetID handling
2024-10-07 21:39:29 +02:00
Pax1601
914d4a4a28
Merge branch 'v2' into srs-integration 2024-10-07 21:39:23 +02:00
Pax1601
4078759310 Added packetID handling 2024-10-07 21:36:14 +02:00
Davide Passoni
e94d296de2 Create 633052.jpg 2024-10-07 18:01:04 +02:00
Davide Passoni
01897019b0 More work on audio system, started adding carrier icon 2024-10-07 18:00:44 +02:00
Pax1601
fc00a4eac4
Merge pull request #935 from Pax1601/srs-integration
Srs integration
2024-09-09 12:31:55 +02:00
Davide Passoni
abd561a60d Completed first implementation of SRS integration 2024-09-09 12:30:54 +02:00
Pax1601
d774977387 First version of external sounds 2024-09-09 08:06:03 +02:00
Davide Passoni
5726d6dee2 More work on external audio sources, started adding generic audio packet handling 2024-09-06 18:12:09 +02:00
Pax1601
9c2ce526d3 Added track controls 2024-09-05 22:35:08 +02:00
Pax1601
9bbcdac704 More work on audio 2024-09-04 19:41:05 +02:00
Davide Passoni
a64ccab15f More work on sources 2024-09-03 20:19:11 +02:00
Pax1601
b352bc824c More work on SRS backend for radio playback and recording 2024-09-02 07:51:51 +02:00
Davide Passoni
ba2c48dead First tests and integration of radio panel 2024-08-31 10:12:25 +02:00
Davide Passoni
ebfa7916c6 Added airbase info and spawn menu 2024-08-29 15:31:16 +02:00
Davide Passoni
fd15406f5d Unit control menu only opens automatically if screen is wide 2024-08-08 15:49:22 +02:00
Davide Passoni
19b0eeeffd Fixed error preventing operation on touch screen for position actions 2024-08-08 15:39:38 +02:00
Davide Passoni
6fdfb194a6 Implemented context menu and multiple control tweaks 2024-08-08 15:32:59 +02:00
Pax1601
7cf77a63be Added deep copy of radio and tacan objects 2024-08-07 15:48:25 +02:00
Pax1601
2e77de95cc Fixed wrong awacs/tanker callsign 2024-08-07 15:45:52 +02:00
Pax1601
2476dac810 Fixed minor errors in tanker/AWACS options 2024-08-07 15:41:51 +02:00
Pax1601
0b2ee1df9b
Merge pull request #933 from Pax1601/890-add-tanker-advanced-settings
890 add tanker advanced settings
2024-08-07 15:34:40 +02:00
Pax1601
224dc5a688 Completed advanced settings panel for tanker and AWACS
Reformatted files with larger width, reordered unused icons
2024-08-07 15:32:39 +02:00
Davide Passoni
bc5049992a Started working on tanker and AWACS settings 2024-08-05 17:07:58 +02:00
Pax1601
cc686e2320
Merge pull request #920 from Pax1601/v2
V2
2024-08-05 16:14:53 +02:00
Pax1601
040476107a
Merge pull request #919 from Pax1601/904-add-unit-loadoutfuelhealth-panel-to-unit-control-panel
904 add unit loadoutfuelhealth panel to unit control panel
2024-08-05 16:07:14 +02:00
Davide Passoni
57f3b84f20 Added fuel and loadout panel, also added search tool 2024-08-05 16:05:51 +02:00
Davide Passoni
b021ddaf11 Started implementing panel, missing loadout summary 2024-08-02 17:33:48 +02:00
Pax1601
e7418a8d6c
Merge pull request #917 from Pax1601/910-add-controls-explanation-section
Closes #910 add controls explanation section
2024-08-02 17:04:55 +02:00
Davide Passoni
9174353b09 Styling completed, controls to be added as functionality is added 2024-08-02 17:03:46 +02:00
Pax1601
e1a566d0d3
Merge pull request #914 from Pax1601/906-add-ability-to-draw-coalition-areas
906 add ability to draw coalition areas
2024-08-02 14:33:06 +02:00
Davide Passoni
a3e92580c2 Completed creation of areas 2024-08-02 13:17:42 +02:00
Pax1601
86e0e6b3a3 Started adding controls panel for shortcuts, more work on better polygon creation, added circles creation 2024-08-01 09:02:21 +02:00
Davide Passoni
1e72f15876 More work on coalition areas drawing 2024-07-31 08:34:59 +02:00
Davide Passoni
2d90c359f7 Added ability to draw coalition areas (WIP) 2024-07-26 17:00:09 +02:00
Pax1601
b993786301
Merge pull request #913 from Pax1601/912-implement-build-scripts-for-reactvite
912 implement build scripts for reactvite
2024-07-26 11:17:11 +02:00
Davide Passoni
faccf48ecd Update package.json 2024-07-25 13:08:31 +02:00
Davide Passoni
c0b43c916e Fixed minor errors in build scripts 2024-07-25 12:35:17 +02:00
Davide Passoni
473f16dda0 Updated react and server build scripts to operate with new UI 2024-07-25 11:38:36 +02:00
Davide Passoni
03de0f9175 Updated build scripts for react website 2024-07-25 10:41:56 +02:00
Davide Passoni
aa7db94750 Merge branch 'v2' into 912-implement-build-scripts-for-reactvite 2024-07-25 10:27:35 +02:00
Davide Passoni
bd3ac54ff8 Update map.ts 2024-07-25 10:23:43 +02:00
Davide Passoni
287f634f74 Merge branch 'release-candidate' into v2 2024-07-25 09:14:00 +02:00
Pax1601
119a6f620c
Merge pull request #901 from Pax1601/main
Main
2024-07-23 18:34:26 +02:00
Pax1601
3e22247f76 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2024-07-23 18:31:49 +02:00
Pax1601
854bef15e0 Update OlympusCameraControl.lua 2024-07-23 18:31:48 +02:00
Pax1601
aacf6d99bc
Merge pull request #900 from Pax1601/release-candidate
Added background arcigs layer
2024-07-23 09:57:59 +02:00
Davide Passoni
a8595a97d8 Added default background arcgis layer 2024-07-23 09:57:01 +02:00
Pax1601
c630fe3045 Update logger.cpp 2024-07-22 18:46:20 +02:00
Pax1601
05c7d8166b
Merge pull request #899 from Pax1601/main
Main
2024-07-22 18:35:09 +02:00
Pax1601
1d3d8ca705 Update logger.cpp 2024-07-22 18:34:39 +02:00
Pax1601
97a11d6873
Merge pull request #898 from Pax1601/release-candidate
Fixed error logger clearing file at all logs
2024-07-22 18:04:18 +02:00
Pax1601
15e23564c2 Fixed error logger clearing file at all logs 2024-07-22 17:57:16 +02:00
Pax1601
42782c60a4
Merge pull request #897 from Pax1601/release-candidate
Manager error fix
2024-07-22 16:53:19 +02:00
Pax1601
62b2b13d75 Fixed error of manager downloading wrong version 2024-07-22 16:51:59 +02:00
Pax1601
8bf2048d4d
Merge pull request #896 from Pax1601/main
Main
2024-07-22 15:48:19 +02:00
Pax1601
0fee5c8e7f
Update version.json 2024-07-22 15:47:57 +02:00
Pax1601
b5e47fdbe6
Merge pull request #895 from Pax1601/release-candidate
Merge release candidate to main for v1.0.4 release
2024-07-22 15:47:29 +02:00
Pax1601
c85e923899 Removed documentation workflow 2024-07-22 15:36:12 +02:00
Pax1601
a897401975 Log is truncated and no longer appended, decrease camera link status check update 2024-07-22 15:31:55 +02:00
Pax1601
2f43a84224
Update version.json 2024-07-18 12:45:46 +02:00
Pax1601
274c16851e Minor update to export scripts and added Kiowa 2024-07-18 10:57:41 +02:00
Pax1601
e77356cb61 Added Afghanistan map 2024-07-18 10:02:17 +02:00
Pax1601
f4e77b1f5b
Merge pull request #894 from Pax1601/release-candidate
v1.0.4
2024-07-17 16:58:13 +02:00
Pax1601
95247062a3 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2024-07-17 16:49:26 +02:00
Pax1601
959b083a60 Added auto installation of VS Redists 2024-07-17 16:49:21 +02:00
Pax1601
395409ecae
Update README.md 2024-07-17 15:51:11 +02:00
Pax1601
5a2b050104
Merge pull request #892 from Pax1601/bobprofisker-patch-1
Update README.md
2024-07-17 15:50:40 +02:00
Pax1601
732b837a46
Update README.md 2024-07-17 15:44:55 +02:00
Pax1601
d60d2e78ef
Update README.md 2024-07-17 15:43:50 +02:00
Pax1601
81b1bf0335 Fixed public folder 2024-07-09 08:38:55 +02:00
Davide Passoni
867dff6945 Transitioned server to typescript 2024-07-09 08:02:40 +02:00
Pax1601
98862d917c Added check on map zooming to disable box select 2024-07-07 19:12:56 +02:00
Pax1601
1dceb0b421 Added ability to box select with long press 2024-07-07 19:10:02 +02:00
Davide Passoni
fbc22676c5 Added box selection for mobiles and ability to drag markers, units can be moved only via context action 2024-07-05 17:26:53 +02:00
Davide Passoni
61e52efc07 Added ability to hide spawn menu 2024-07-05 12:12:21 +02:00
Pax1601
fa48d1f905 More work on small screens 2024-07-03 19:38:32 +02:00
Davide Passoni
5f3dbbf94e Added settings for linting 2024-07-03 09:57:51 +02:00
Davide Passoni
96b3e2f115 More work on responsive design for small screens 2024-07-02 17:36:53 +02:00
Davide Passoni
00e2da2aab Reformatted project using prettier plugin 2024-07-01 17:43:46 +02:00
Davide Passoni
1acb7d6762 Work on reactive design 2024-07-01 15:51:43 +02:00
Davide Passoni
b3f8eb96ad Added automatic removal of vite proxy 2024-06-28 11:29:44 +02:00
Davide Passoni
36478f26d5 Added ability to preview on proxy 2024-06-28 11:25:30 +02:00
Davide Passoni
e07bf98e62 Re-enabled login page 2024-06-28 11:09:29 +02:00
Davide Passoni
cd38a2f053 Added context buttons, temporary fixes to allow preview 2024-06-28 11:04:18 +02:00
Pax1601
329e9b86fd Merge branch 'v2' of https://github.com/Pax1601/DCSOlympus into v2 2024-06-27 20:02:59 +02:00
Pax1601
1e48df85a7 Fixed callback error on loading of URi 2024-06-27 20:02:53 +02:00
Davide Passoni
8cb8f7e108 More work on context actions 2024-06-27 17:35:10 +02:00
Davide Passoni
222a296b4f Readded map options, simplified ShortcutManager 2024-06-27 14:46:28 +02:00
Davide Passoni
fb96926d1e Merge branch 'release-candidate' into v2 2024-06-27 11:41:52 +02:00
Davide Passoni
a15d2e2ec7 Fixed incorrect removal of airbases on map when changing layer 2024-06-27 11:40:47 +02:00
bobprofisker
df1839cee0
Update README.md 2024-06-23 23:22:16 +01:00
Pax1601
1b4d3dd832 Added configuration parameters for vcpkg 2024-06-17 17:56:33 +02:00
Pax1601
13e75e9dd1 Configuration change 2024-06-14 19:08:10 +02:00
Davide Passoni
0e414850bd All map layers and mirrors moved to config (THANKS WIRTS) 2024-06-13 16:26:12 +02:00
Pax1601
40e984982b Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2024-06-11 17:55:47 +02:00
Pax1601
d7c278b034 Minor bugfix in map creator scripts 2024-06-11 17:55:44 +02:00
Davide Passoni
79016d72e3 More work on unit context actions 2024-06-11 16:19:29 +02:00
Davide Passoni
b089a8cfd8 Merge branch 'react-transition-test' into v2 2024-06-07 11:46:40 +02:00
Davide Passoni
a9f4353e4a Fixed error in spawn menu (unable to select coalition) and cropped unit images for spawn menu 2024-06-07 11:34:51 +02:00
Davide Passoni
4acbe375a7 Small change in how units are represented in the unit spawn menu 2024-06-07 08:56:00 +02:00
Davide Passoni
a9a6b18943 Added minimap summary panel 2024-06-06 17:14:07 +02:00
Davide Passoni
9c53e0605b Merge branch 'release-candidate' into v2 2024-06-06 12:09:52 +02:00
Pax1601
4e679344d0
Merge pull request #891 from Pax1601/automatic-map-config
Added automatic read of config file to setup map layers
2024-06-06 12:08:55 +02:00
Davide Passoni
b0ab0ae8cf Added automatic read of config file to setup map layers 2024-06-06 12:08:34 +02:00
Pax1601
6edcd8a5ce
Merge pull request #889 from Pax1601/db-updates
Db updates
2024-05-29 16:12:07 +02:00
Pax1601
aa0cca67a1 Added HB F-4 to databases 2024-05-29 16:05:57 +02:00
Pax1601
c477dcd065 Updated python scripts 2024-05-29 15:49:37 +02:00
Pax1601
6db4455d5a Tony's update to unit databases 2024-05-29 09:20:37 +02:00
Pax1601
54bf19d410
Merge pull request #888 from Pax1601/kola-map
Kola map
2024-05-29 09:01:08 +02:00
Davide Passoni
0c93b950c6 Updated launch tasks for auto installation 2024-05-28 10:20:50 +02:00
Pax1601
52833cadee Added configuraiton files for caucasus 2024-05-26 19:27:52 +02:00
Davide Passoni
6a45bc9e79 Added configuration files for syria and caucasus 2024-05-26 19:15:41 +02:00
Pax1601
88d17d1cb3 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2024-05-23 20:21:12 +02:00
Pax1601
8c27fdb53c Improvements in map generator script 2024-05-23 20:21:09 +02:00
Davide Passoni
e7777a2a48 Added configuration files for different maps 2024-05-23 20:17:25 +02:00
bobprofisker
fa4a0ccecb
add constant.ts kola map
add constant.ts kola map
2024-05-19 13:49:06 +01:00
bobprofisker
b54aa45377
kola.json add airbases list
added the kola.json airbase list of information for runways, ils, tacan etc
2024-05-19 13:42:31 +01:00
bobprofisker
eecdcad8e7
airbases.js add kola
addedd kola theatre
2024-05-19 13:39:09 +01:00
bobprofisker
d68ac6cf2b
index.d.ts kola
added kola to index
2024-05-19 13:11:42 +01:00
Pax1601
e39b6b5eea Update .gitignore 2024-05-18 17:51:59 +02:00
Pax1601
53a43b5536 More work on new ui 2024-05-18 17:51:22 +02:00
Pax1601
4eb1b3ef6d
Update README.md 2024-05-14 21:02:03 +02:00
Pax1601
4204a4b150
Merge pull request #887 from Pax1601/Pax1601-patch-1
Update README.md
2024-05-14 21:00:16 +02:00
Pax1601
b64d336922
Update README.md 2024-05-14 21:00:05 +02:00
Dogma
3e465509e9 Updated login to include Olympus Logo 2024-05-07 21:52:39 +10:00
Dogma
79c8e743d9 Misc Changes [Login]
- Updated styling
- Added image back in to bg
- Updated card styling
- Updated bg opacity
- Updated callouts
- Modified login elements
- Removed guide buton
2024-05-03 15:23:55 +10:00
Dogma
0f882c9c33 Small Tweak [Login]
- Small update to size of login window
2024-05-03 00:22:54 +10:00
Dogma
3ddafa4fff Additional responsive changes [Login]
- Updated responsive design for login screen to go fill the entire screen when on small screen sizes i.e. mobile
2024-05-03 00:20:10 +10:00
Dogma
5c4b09735a Updated Callout Component
- Added variations of callout component
- Updated error messaging on login
2024-05-02 23:55:49 +10:00
Davide Passoni
f5aca98e49 More work on login connection logic 2024-05-02 10:05:12 +02:00
Dogma
2cb3287d1f Minor update to login
- Fixed up password field not filling container
2024-05-02 16:41:29 +10:00
Dogma
b96254c9f2 Further work on login screen
- Added Cards on right side
- Fixed up placement of privacy notice
- Fixed responsiveness
2024-05-02 16:38:51 +10:00
Dogma
f6fbd5c931 Minor fixes missed in last change
- Woops lol
2024-05-01 21:48:57 +10:00
Dogma
e622067230 Updated UI of Login Screen
- Fixed styling
- Added first layer of responsive design
2024-05-01 21:46:10 +10:00
Pax1601
c4e484706a Started working on login panel 2024-05-01 11:57:51 +02:00
Dogma
37a89e4548 Multiple updates
- Added bottom buttons to sidebar
- Fixed up various UI issues
- Added options panel that now works
2024-04-18 14:59:23 +10:00
Dogma
d0e0d851db Small UI Tweaks
I updated a bunch of things because I can - mainly for consistency etc
2024-04-18 00:28:26 +10:00
Dogma
9df0fb9425 Updated background colours for menu
- Updated colours to include blur effect
- Looks cool, fight me
2024-04-17 23:39:00 +10:00
Dogma
c6300b3e6a Updated IP and Link to be dynamic
IP Address of server and connection status is now sourced from 'olympusapp'  and automatically updates status in the header.
2024-04-17 19:03:59 +10:00
Davide Passoni
6296bdc2d8 Small tweak to setupApp callback 2024-04-16 17:28:52 +02:00
Dogma
627c19e550 Updates to header
- Add Connected message to header
- Updated control panel heading
2024-04-16 22:13:27 +10:00
Dogma
dcacf617d7 Added SAM image to SAM Sites 2024-04-16 21:23:03 +10:00
Dogma
fceb27505d Updated Control Menu UI
- Updated Unit Selected bar to fix padding and font
2024-04-15 23:03:18 +10:00
Dogma
4b431a7f90 Various UI Tweaks
- Various UI Tweaks
- Added hover states to many components
2024-04-15 22:50:18 +10:00
Dogma
413285f03d Main Menu Updated
- Main Menu updated to include dividers and subtext
- Heading of menu updated to fix padding
2024-04-15 22:07:58 +10:00
Dogma
8a3db4083f Updated Main Menu
- Updated iconography
- Included animation
- Adjusted colours etc
2024-04-15 21:41:51 +10:00
Dogma
f847d4713b Update lock to default locked
As above
2024-04-15 21:14:00 +10:00
Dogma
15bec68fc4 Updated Heading Round Buttons
- Updated iconography on some Round Buttons (coalition toggle)
- Added new type: LockStateButton
- New LockStateButton is setup to automatically switch icon whether it's checked or not at the component level and no longer expects icon to be provided.
2024-04-15 21:13:26 +10:00
Dogma
58b5eacdb7 Minor updates to components
- Minor changes to components such as label and number changer
2024-04-15 20:35:27 +10:00
Dogma
95f8eb0976 Various UI Changes
- Various UI Changes and fixes to various components and panels
- Added formatting to Altitude Control to include comma automatically
2024-04-15 19:59:04 +10:00
Dogma
c3fb3fa9c1 Updates to control menu
- Updated UI for control menu
2024-04-14 23:20:30 +10:00
Dogma
73bf1da061 Updated Panel Colours, Main Menu
- Updated the colours of all panels to match new Olympus values
- Updated button colours and included hover state
- Updated Main Menu
2024-04-14 23:08:06 +10:00
Dogma
e040ecfce2 Various Small UI Tweaks
- Adjustments to a number of UI components, including Label Toggle, Spawn menu, Dropdowns etc
2024-04-14 22:36:20 +10:00
Dogma
32f5f01f5c Updated Unit Spawn Menu
- UI Updates to Unit Spawn Menu
2024-04-14 21:48:35 +10:00
Dogma
b4e217548e Updated Font and Unit Summary
- Font updated to Inter
- UI Changes to Unit Summary Component
2024-04-14 21:38:10 +10:00
Dogma
dab1d4a97c Merge branch 'react-transition-test' of https://github.com/Pax1601/DCSOlympus into react-transition-test 2024-04-14 20:40:24 +10:00
Dogma
8d21149db7 Added Olympus Colours
- Added Olympus Colours
- First commit yay
2024-04-14 20:39:02 +10:00
Pax1601
288df71970 Started working on unit spawning 2024-04-14 12:34:38 +02:00
Davide Passoni
40df2ebb7d More work on unit control panel 2024-04-12 17:53:03 +02:00
Davide Passoni
c7ecd2422a Started working on unit control panel, typed props 2024-04-11 17:29:23 +02:00
Pax1601
f18212dac4 More wore on components 2024-04-11 08:10:34 +02:00
Davide Passoni
45e290d656 More work on React components 2024-04-09 18:12:05 +02:00
Pax1601
8e9e6749db More tests on react components 2024-04-08 08:49:05 +02:00
Pax1601
19c1ae82a2 Configurable wait period added 2024-04-06 15:47:27 +02:00
Pax1601
f056cc62a8 More work on flowbite components 2024-04-06 15:42:53 +02:00
Davide Passoni
90ccf57f01 Testing work with flowbite 2024-04-05 17:50:59 +02:00
Pax1601
d72a00a005 Started readding old core frontend code 2024-04-03 08:05:36 +02:00
Pax1601
5d5c650162 Added state and events context 2024-04-02 15:18:10 +02:00
Davide Passoni
42c7a36da7 Started building react app 2024-03-30 08:40:02 +01:00
Pax1601
61dc9c8b31 Added compression step to image generation 2024-03-23 13:18:00 +01:00
Pax1601
d078105eb7
Merge pull request #886 from Pax1601/740-ships-might-not-be-able-to-shoot-at-points-anymore-ie-tomahawk-stuff
Fixed bug that stopped ships from firing at area
2024-03-20 16:58:57 +01:00
Pax1601
7ee9946f49 Fixed bug that stopped ships from firing at area 2024-03-20 16:56:25 +01:00
Pax1601
5507bca68d
Merge pull request #885 from Pax1601/857-file-import-fails-if-alt-value-present-in-targetposition-entry
857 file import fails if alt value present in targetposition entry
2024-03-20 16:43:13 +01:00
Pax1601
535b95242c Made separation larger for ships 2024-03-20 16:42:46 +01:00
Pax1601
e40b79d2c4 Added fix for navy units too 2024-03-20 16:34:50 +01:00
Pax1601
ecd0581942 When spawning multiple ground units they are now arranged in square, and no longer one on top of the other 2024-03-20 16:33:51 +01:00
Pax1601
4f7c3988a0
Merge pull request #884 from Pax1601/857-file-import-fails-if-alt-value-present-in-targetposition-entry
Made target position optionally vec2 or vec3
2024-03-20 16:04:08 +01:00
Pax1601
5b7e63b02d Made target position optionally vec2 or vec3 2024-03-20 16:03:39 +01:00
Pax1601
ef99c21380
Merge pull request #883 from Pax1601/862-iads-creator-not-spawning-units
Added missing default values for skill of ground units in IADS generator
2024-03-18 08:34:23 +01:00
Pax1601
e0ad679b57 Added missing default values for skill of ground units in IADS generator 2024-03-18 08:33:57 +01:00
Pax1601
61fb80d67f
Merge pull request #882 from Pax1601/856-camera-control-produces-jerky-movement-on-browsers-different-from-chrome
Fixed camera control on Firefox, added slider to control zoom level, …
2024-03-17 15:58:24 +01:00
Pax1601
a9a0332465 Fixed camera control on Firefox, added slider to control zoom level, and other improvements 2024-03-17 15:58:05 +01:00
Pax1601
4494a5ccbb
Merge pull request #879 from Pax1601/https-test
Added ability to enable https in express
2024-03-13 15:06:05 +01:00
Davide Passoni
f0c4b10084 Added ability to enable https in express 2024-03-13 15:05:30 +01:00
Pax1601
0bdf362174 Improved and generalized DCS maps handling 2024-03-13 15:01:35 +01:00
Pax1601
a53cca8dda
Merge pull request #877 from Pax1601/manager-improvements
Multiple manager improvements and bug fixes
2024-03-11 17:26:01 +01:00
Davide Passoni
9aad81588a Minor manager bugfixes 2024-03-11 17:25:35 +01:00
Davide Passoni
5ba1498802 Map generation improvements 2024-03-11 16:57:50 +01:00
Davide Passoni
539b183da8 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2024-03-11 15:37:21 +01:00
Pax1601
396c061a3e Multiple manager improvements and bug fixes 2024-03-10 18:38:55 +01:00
Pax1601
8c7f6abb1c Added more configurability to map generator 2024-03-10 13:43:09 +01:00
Pax1601
5cc42dd9cf Embedded DCS maps directly into website 2024-03-10 10:13:25 +01:00
Pax1601
f52b5f419e
Merge pull request #861 from Pax1601/855-map-generator-fails-when-a-single-put-request-is-dropped
855 map generator fails when a single put request is dropped
2024-03-08 16:28:08 +01:00
Pax1601
3b38ca5920
Merge pull request #860 from Pax1601/853-proxy-middleware-reroutes-to-address-if-backend-api-is-enabled
If address is *, proxy middleware reroutes to localhost
2024-03-08 16:27:42 +01:00
Pax1601
86cfb4fb2f
Merge pull request #859 from Pax1601/858-export-to-file-files-nothing-happens-when-the-button-is-clicked
Fixed checkbox not working in export screen
2024-03-08 16:26:55 +01:00
Davide Passoni
166631d618 Increased pixel sweep when calibrating 2024-03-08 16:23:59 +01:00
Davide Passoni
013546a45b Fixed checkbox not working in export screen 2024-03-08 16:22:30 +01:00
Davide Passoni
a2c8563adf Added argpars for better control of script execution 2024-03-08 16:04:55 +01:00
Davide Passoni
0c8de2dcf3 Added retry algorithm for put request and timestamps 2024-03-08 09:24:52 +01:00
Davide Passoni
4f3491062b If address is *, proxy middleware reroutes to localhost 2024-03-07 17:36:50 +01:00
Pax1601
cc8c25a283
Merge pull request #852 from Pax1601/advanced-map-layers
Advanced map layers
2024-03-07 17:21:46 +01:00
Davide Passoni
70740233a9 Create map_generation.md 2024-03-07 13:14:50 +01:00
Pax1601
f2d4f0b0ca Fixed layer resolution 2024-03-06 16:42:58 +01:00
Davide Passoni
153ca01b96 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2024-03-05 15:16:18 +01:00
Pax1601
f667410a56 Merge branch 'release-candidate' of https://github.com/Pax1601/DCSOlympus into release-candidate 2024-03-05 00:28:03 +01:00
Pax1601
f13545eae9 Edited installation message, fixed dev environment for server 2024-03-05 00:27:35 +01:00
Davide Passoni
7ee24b1c7c More work on docs 2024-03-04 18:08:06 +01:00
Davide Passoni
29784310fc Started updating docs 2024-03-04 17:38:34 +01:00
Davide Passoni
3427fcea7e Removed unnecessary dependency 2024-03-04 11:09:10 +01:00
Pax1601
c99b5ed19f Added calibration to map generator 2024-03-04 08:41:24 +01:00
Davide Passoni
2118ded496 More general handling of zoom levels 2024-02-29 17:22:29 +01:00
Davide Passoni
4401261446 Merge branch 'release-candidate' into advanced-map-layers 2024-02-29 17:11:04 +01:00
Davide Passoni
a6ec3a8cd0 Fixed error in updater code 2024-02-29 16:06:03 +01:00
Davide Passoni
6e6da64c51 Added ability to define map layers 2024-02-29 16:05:21 +01:00
Pax1601
a84e190548
Merge pull request #851 from Pax1601/camera-control
Implemented camera control from Olympus to DCS
2024-02-29 12:22:45 +01:00
Davide Passoni
e0238c2680 Removed DCS map from default json 2024-02-29 12:12:34 +01:00
Davide Passoni
a60f2e7b62 Modified website to keep camera link if dropped 2024-02-29 12:11:11 +01:00
Davide Passoni
4782596e3c Added installation/deletion of camera control plugin from manager 2024-02-29 10:54:52 +01:00
Pax1601
832568aa00 Completed camera control server in lua and more work on merging algorithm 2024-02-28 18:58:40 +01:00
Davide Passoni
05e0cc393a Complete camera control UI 2024-02-27 16:46:11 +01:00
Pax1601
c74258e3ad Completed automatic algorithm 2024-02-26 08:55:03 +01:00
Davide Passoni
2e1c3ec4b9 Added ability to add more map sources 2024-02-23 16:25:19 +01:00
Davide Passoni
9a571132c8 Refined automatic map generation script 2024-02-23 15:54:49 +01:00
Davide Passoni
acb55044d1 More work on automatic map creation 2024-02-22 17:46:34 +01:00
Pax1601
14679bd7d8 Added code for map creation and camera control 2024-02-22 08:01:13 +01:00
Pax1601
3c9af59051
Merge pull request #849 from Pax1601/848-add-zip-only-release-folder
Added script to produce zip only version
2024-02-20 11:41:20 +01:00
Davide Passoni
8390a25c50 Fixed error in elevation routes
Was hardcoded to load relative config file
2024-02-20 11:38:02 +01:00
Davide Passoni
97b277edda Added script to produce zip only version 2024-02-20 11:23:48 +01:00
Pax1601
462fa53c80
Merge pull request #847 from Pax1601/745-script-error-on-getpayload
Update mist.lua
2024-02-20 10:26:25 +01:00
Davide Passoni
945c45803b Update mist.lua 2024-02-20 10:25:49 +01:00
Pax1601
20917da437
Merge pull request #844 from Pax1601/713-number-of-selected-units
Number of selected units now shown
2024-02-20 09:36:21 +01:00
Davide Passoni
cd25509d3d Merge branch 'release-candidate' into 713-number-of-selected-units 2024-02-20 09:35:32 +01:00
Pax1601
4c3f80d7d7
Merge pull request #837 from Pax1601/673-status-bar-hit-box
Rapid controls' box now overflows un-obstructively
2024-02-20 09:35:02 +01:00
Davide Passoni
fac32476d4 Merge branch 'release-candidate' into 673-status-bar-hit-box 2024-02-20 09:33:35 +01:00
Davide Passoni
3fa88f3cdf Update .gitignore 2024-02-20 09:31:07 +01:00
Pax1601
46135f7ae0
Merge pull request #846 from Pax1601/separate-client
Separate client
2024-02-19 19:29:31 +01:00
Pax1601
f6e9503045 Removed test script 2024-02-19 18:54:25 +01:00
Davide Passoni
39c28ffb04 Added problem matchers 2024-02-19 16:45:55 +01:00
Davide Passoni
6373fd300d Fixed output for build debug 2024-02-19 15:52:20 +01:00
Davide Passoni
04f281db56 Fixed babel preset-env 2024-02-19 15:48:26 +01:00
Davide Passoni
5f2fb60e1f Added build debug step in check_setup 2024-02-19 15:41:40 +01:00
Davide Passoni
4efd48c4b9 Added check on correct setup of the environment 2024-02-19 15:34:39 +01:00
PeekabooSteam
fb6ac40af8 Number of selected units now shown 2024-02-11 15:55:13 +00:00
PeekabooSteam
9daa683b42 Rapid controls' box now overflows unobsctrutively 2024-02-11 12:58:32 +00:00
Pax1601
baffc9af49
Merge pull request #826 from Pax1601/813-fix-last-details-of-the-manager
Fixed broken guide links
2024-02-10 10:29:15 +01:00
Pax1601
bc6c70928f Updated plugin scripts to new structure
Fixed copy scripts for plugins
2024-02-08 22:55:44 +01:00
Pax1601
9e1503c106 Renamed server->backend in configuration files 2024-02-08 22:29:26 +01:00
Pax1601
57a700d2d2 Renamed client -> frontend in configuration files
Completed renaming client -> frontend
2024-02-08 22:26:36 +01:00
Pax1601
5ca6c97cbe Split client into frontend website and server 2024-02-08 22:04:23 +01:00
Pax1601
55f3bd5adb
Merge pull request #823 from WoodyXP/Fix-Semicolumn-Skill
Fix semicolumn skill
2024-02-08 08:45:11 +01:00
Stefan Arsic
bf7c4beccd
Update OlympusCommand.lua 2024-02-08 00:19:47 +01:00
Stefan Arsic
14d44babe7 Added missing semicolumn 2024-02-08 00:16:09 +01:00
Stefan Arsic
30a90a96d8 Merge branch 'Fix-Semicolumn-Skill' of https://github.com/WoodyXP/DCSOlympus into Fix-Semicolumn-Skill 2024-02-08 00:15:11 +01:00
Stefan Arsic
c621b5dd85 Added missing semicolumn1 2024-02-08 00:13:42 +01:00
Pax1601
63bdf44e17
Merge pull request #821 from WoodyXP/681_newest_changes_skill
681 newest changes skill
2024-02-07 18:12:11 +01:00
Pax1601
029decf969
Merge pull request #819 from Pax1601/PeekabooSteam-patch-1
Update index.ejs
2024-02-07 08:56:50 +01:00
WoodyXP
b5c7eaf36e Change the name of default livery 2024-02-06 13:36:22 +01:00
WoodyXP
99de17a858 Merge branch '681_newest_changes_skill' of https://github.com/WoodyXP/DCSOlympus into 681_newest_changes_skill 2024-02-06 11:11:40 +01:00
WoodyXP
5765ade7f8 Change the location of the skill select 2024-02-06 11:11:16 +01:00
Stefan Arsic
59a8fba14d
Made unit.skill instead of just skill 2024-02-06 09:43:24 +01:00
WoodyXP
965b67b8ab Sort SkillDropdown by Skill level 2024-02-06 09:27:55 +01:00
Stefan Arsic
0ef3abbffa
Merge branch 'Pax1601:release-candidate' into 681_newest_changes_skill 2024-02-03 22:42:28 +01:00
Stefan Arsic
2124e9cd42 Fixed setting skill level 2024-02-03 22:29:26 +01:00
PeekabooSteam
2f1a0ad7d3
Update index.ejs 2024-01-31 15:50:47 +00:00
Pax1601
24e6c219f5 Fixed broken guide links 2024-01-31 16:41:28 +01:00
Pax1601
daec6dab5b
Merge pull request #818 from Pax1601/813-fix-last-details-of-the-manager
Fixed missing sleep in popup callback
2024-01-31 15:42:38 +01:00
Pax1601
3708d4150c Fixed missing sleep in popup callback 2024-01-31 15:40:31 +01:00
Pax1601
11518485de
Merge pull request #817 from Pax1601/813-fix-last-details-of-the-manager
Fixed error in port detection and default radio buttons values
2024-01-31 14:51:59 +01:00
Pax1601
29118e1ea1 Fixed error in port detection and default radio buttons values 2024-01-31 14:51:42 +01:00
Pax1601
aa5b62c1d2
Merge pull request #816 from Pax1601/813-fix-last-details-of-the-manager
Finished manager bugfix
2024-01-31 13:00:40 +01:00
Pax1601
f320cb122c Finished manager bugfix 2024-01-31 12:59:46 +01:00
Pax1601
bb7738724f
Merge pull request #815 from Pax1601/813-fix-last-details-of-the-manager
813 fix last details of the manager
2024-01-30 18:56:59 +01:00
Pax1601
df7eebed39 Added temporary message if no instances detected 2024-01-30 18:56:37 +01:00
Pax1601
21040da195 Added expert settings mode 2024-01-30 17:45:25 +01:00
Pax1601
be625fdca9 Removed autoselection of radio buttons in wizard 2024-01-29 17:52:33 +01:00
Pax1601
7ee3fb883b Added success/failure banner and fixed instance status 2024-01-29 13:24:09 +01:00
Pax1601
c2f6edfd74 Minor refactoring of css, fixed graphical inconsistencies 2024-01-28 16:37:29 +01:00
Pax1601
4f5023b45c Added fade transition between pages 2024-01-28 15:14:30 +01:00
Pax1601
f0ab43d320
Merge pull request #812 from Pax1601/manager-wizard
Bugfixing on manager
2024-01-28 10:22:19 +01:00
Pax1601
d2e803ab82 Bugfixing on manager 2024-01-28 10:21:12 +01:00
Pax1601
ca45b8b906
Merge pull request #808 from Pax1601/807-stop-search-engines-indexing-servers
Added noindex
2024-01-26 17:35:30 +01:00
Pax1601
ec020f7b5d
Merge pull request #811 from Pax1601/manager-wizard
Manager wizard
2024-01-26 17:34:51 +01:00
Pax1601
f2161da162 Completed basic functionality development 2024-01-26 17:31:36 +01:00
Pax1601
613aed2d2b Added config page and loading bars 2024-01-25 17:42:16 +01:00
Pax1601
1d38bd6fea Added folder selection page and port availability checks 2024-01-24 19:08:42 +01:00
Pax1601
6f7b251094 Readded dashboard to manager 2024-01-23 08:01:34 +01:00
PeekabooSteam
a9d873a05f Added noindex 2024-01-18 06:30:56 +00:00
Pax1601
05f98b2738 Work on result page 2024-01-17 20:14:22 +01:00
Pax1601
1568c65492 Implement more wizard page, result page still wip 2024-01-17 17:51:27 +01:00
Pax1601
4a5c4ed7d7 Merge branch 'manager-wizard' of https://github.com/Pax1601/DCSOlympus into manager-wizard 2024-01-17 08:08:33 +01:00
Pax1601
ff7385cf49 Update tasks.json 2024-01-17 08:08:29 +01:00
Pax1601
a0de159234 More work on new manager design 2024-01-16 17:45:52 +01:00
Pax1601
d56a95cfa3 Added distinction between basic and advanced mode 2024-01-13 10:01:30 +01:00
Stefan Arsic
497f718e4b Added option for ground units to change skill 2024-01-12 22:33:43 +01:00
Stefan Arsic
9942ff476b Made the skill work 2024-01-11 19:41:04 +01:00
WoodyXP
c042d2b6f5 Changes 2024-01-11 17:37:28 +01:00
WoodyXP
b9201d583c Added tiny fixed 2024-01-11 14:16:19 +01:00
Pax1601
3f67125f20 Fixed missed call to copy.bat 2024-01-11 09:55:48 +01:00
WoodyXP
4f72f10642 Commiting uncommited files 2024-01-11 09:28:39 +01:00
WoodyXP
89fb0a9da1 Hopefully added something that can make the flight skill change 2024-01-11 09:10:35 +01:00
Pax1601
0e9b249bba
Merge pull request #804 from Pax1601/manager-wizard
Manager wizard
2024-01-10 11:30:20 +01:00
Pax1601
0f0ba4c725 Added spinner when starting Olympus 2024-01-10 11:29:18 +01:00
Pax1601
5542109daf Merged view and update pages according to new design 2024-01-09 17:33:20 +01:00
Pax1601
ec91b597c8 Update dcsinstance.js 2024-01-04 17:11:46 +01:00
Pax1601
d0f85ae977
Merge pull request #803 from Pax1601/manager-wizard
Made instructions clearer and removed folder deletion on update
2024-01-04 16:04:22 +01:00
Pax1601
7d6930fba9 Made instructions clearer and removed folder deletion on update 2024-01-04 16:03:38 +01:00
Pax1601
2232a114b7
Merge pull request #802 from Pax1601/manager-wizard
Version is now checked on manager startup
2024-01-04 14:53:39 +01:00
Pax1601
33ce537993 Version is now checked on manager startup 2024-01-04 14:53:03 +01:00
Pax1601
1ab8e9a16f
Merge pull request #801 from Pax1601/manager-wizard
Manager wizard
2024-01-04 13:04:10 +01:00
Pax1601
73b1714191 Merge branch 'release-candidate' into manager-wizard 2024-01-04 13:03:44 +01:00
Pax1601
cb793e9d0f Fixed debug scripts for client 2024-01-04 13:02:03 +01:00
Pax1601
7686a60bfd Added log file 2024-01-04 12:10:01 +01:00
Pax1601
38027b6ff3 Added debug options in package folder for manager 2024-01-04 11:05:47 +01:00
Pax1601
a512b0e405 Update package.json 2024-01-04 10:26:34 +01:00
Pax1601
46fb6a98d5 Increased version in dlls rc files 2024-01-04 10:14:46 +01:00
Pax1601
1a8a19ae5c Added ability to retain user-editable files 2024-01-04 10:13:34 +01:00
Pax1601
8865ded4bd Split increase_version file to work with build folder 2024-01-04 09:51:43 +01:00
Pax1601
7adfe9cce4 Update INSTRUCTIONS.txt 2024-01-04 09:40:23 +01:00
Pax1601
85e5a6a309 Fixed wrong url for databases api call 2024-01-03 18:50:16 +01:00
Pax1601
d681d3cee0 Fixed error in database api 2024-01-03 18:44:06 +01:00
Pax1601
c5650ba29a Moved location of databases 2024-01-03 18:20:51 +01:00
Pax1601
ef0a2d2ddc Modified increase_version.js to operate on build folder 2024-01-03 18:08:16 +01:00
Pax1601
f143e8d874 Update build_package.bat 2024-01-03 18:06:01 +01:00
Pax1601
89c1660988 Fixed errors in build scripts 2024-01-03 18:05:16 +01:00
Pax1601
4e7c8ef856 Refactoring of building scripts 2024-01-03 17:48:38 +01:00
Pax1601
8024db9579 Renamed src to backend 2024-01-03 16:19:16 +01:00
Pax1601
a0634a7f99 Documented manager code 2024-01-03 15:08:06 +01:00
Pax1601
7bf6c1bb23 Update preload.js 2024-01-03 13:33:58 +01:00
Pax1601
a62ae4e21e Added check on github api for latest release 2024-01-03 13:25:27 +01:00
Pax1601
6c466a8bb8 Implemented automatic updating 2024-01-03 13:12:04 +01:00
Pax1601
36f828acb1
Merge pull request #797 from Pax1601/manager-wizard
Added package url to version.json for autoupdate
2024-01-03 10:07:46 +01:00
Pax1601
046e096b9e Added package url to version.json for autoupdate 2024-01-03 09:44:12 +01:00
Pax1601
82df3cb316 Delete duplicate build CI step 2024-01-03 09:27:24 +01:00
Pax1601
1ba16f82e7
Merge pull request #796 from Pax1601/main
Main
2024-01-03 09:23:02 +01:00
Pax1601
72c6bb0086
Merge pull request #776 from Pax1601/739-spawn-history
739 spawn history
2024-01-03 09:19:42 +01:00
Pax1601
8bb4334187 Delete package-lock.json 2024-01-03 09:19:27 +01:00
Pax1601
59a9069d4b
Merge pull request #734 from Dahlgren/feature/docker
Basic Docker image for client app
2024-01-03 09:18:28 +01:00
Pax1601
ba534f1786
Merge pull request #737 from Dahlgren/ci/github-actions-client
CI workflow for client build on PRs
2024-01-03 09:17:45 +01:00
Pax1601
72bb54bde0
Merge pull request #785 from Pax1601/722-unit-eras-in-alphabetical-order-instead-of-chronological-order
Set ordering of eras in command mode settings
2024-01-03 09:14:15 +01:00
Pax1601
cb3f46303c
Merge pull request #788 from Pax1601/779-add-json-validation
779 add json validation
2024-01-03 09:13:38 +01:00
Pax1601
57f021f995
Merge pull request #790 from Pax1601/786-disable-command-mode-settings-until-enabled
Disabled options and applied faded styling
2024-01-03 09:11:10 +01:00
Pax1601
bf4b2272e4
Merge pull request #789 from SevFle/725-configurator-different-passwords
725 Add check for duplicate passwords in configurator
2024-01-01 22:05:03 +01:00
Pax1601
31999ec00c
Merge pull request #793 from Pax1601/manager-wizard
Manager wizard
2024-01-01 22:03:07 +01:00
Pax1601
086b6736b0 Added desktop shortcuts 2024-01-01 18:48:31 +01:00
Pax1601
bf93b8e90a Added simplified mode and disabled not useful buttons 2024-01-01 18:19:56 +01:00
PeekabooSteam
4d6bd6c6e9 Disabled options and applied faded styling 2023-12-31 14:04:54 +00:00
Pax1601
c9dc5eb2f5 Added ability to start/stop client 2023-12-31 12:02:24 +01:00
SevFle
5fdb704d68 Add check for duplicate passwords 2023-12-30 10:43:51 +01:00
Pax1601
6d18e25232
Merge pull request #787 from Pax1601/manager-wizard
Modified manager to new design
2023-12-29 11:29:30 +01:00
Pax1601
7391006a2f Modified manager to new design 2023-12-29 11:28:28 +01:00
PeekabooSteam
9207585f5b Set ordering of eras in command mode settings 2023-12-28 17:45:21 +00:00
PeekabooSteam
cb53da3a71 More style tweakage 2023-12-28 16:56:29 +00:00
PeekabooSteam
d2ac5aeff8 Tweaked tab position to be a pinch lower 2023-12-28 16:27:28 +00:00
PeekabooSteam
b646087026 Buttons now have cute icons ^_^ 2023-12-28 16:07:04 +00:00
PeekabooSteam
82e60cd2cf Added more info for when enums aren't matched 2023-12-28 14:10:51 +00:00
Björn Dahlgren
9d46a1c73f Basic Docker image for client app 2023-12-27 23:49:54 +01:00
PeekabooSteam
955057183d Added JSON validation for imports. 2023-12-27 16:26:31 +00:00
Pax1601
0396d6bf9c
Update README.md 2023-12-23 16:01:12 +01:00
Pax1601
ee1d89007c
Update README.md 2023-12-23 15:59:26 +01:00
Pax1601
4245927a6c
Update build_package.yml 2023-12-23 08:27:02 +01:00
Pax1601
f585828936
Merge pull request #782 from Pax1601/manager-wizard
Manager wizard
2023-12-22 21:28:47 +01:00
Pax1601
7450c9e506 Update install.bat 2023-12-22 21:28:26 +01:00
Pax1601
d957cd6655 Merge branch 'manager-wizard' of https://github.com/Pax1601/DCSOlympus into manager-wizard 2023-12-22 21:26:17 +01:00
Pax1601
ef91f840ae Update package.json 2023-12-22 21:26:12 +01:00
Pax1601
17c74fbe91
Merge pull request #781 from Pax1601/manager-wizard
Manager wizard
2023-12-22 19:23:35 +01:00
Pax1601
17a7a1889e
Merge branch 'release-candidate' into manager-wizard 2023-12-22 19:23:25 +01:00
Pax1601
24ed96b348 Manager installation process completed 2023-12-22 19:22:49 +01:00
Pax1601
15e8c9e791 Completed installation procedure on wizard 2023-12-22 18:44:31 +01:00
PeekabooSteam
de14f6c738 Airbase data being validated 2023-12-22 15:11:59 +00:00
Pax1601
92b1a46e8a Started wizard implementation 2023-12-21 18:06:59 +01:00
Pax1601
cbaadb6fc9 Added fallback if powershell not installed 2023-12-21 15:33:28 +01:00
Pax1601
44295673dc Fixed typo and uninstallation error 2023-12-21 15:13:20 +01:00
Pax1601
8bf0f403e2 Updated instructions 2023-12-21 12:00:40 +01:00
Pax1601
917a0d10e5 Update package.bat 2023-12-21 11:44:58 +01:00
Pax1601
9c65411733 Updated installation method, remove installer 2023-12-21 11:44:11 +01:00
PeekabooSteam
6c315d89e1 Finished styling; menu closes on click 2023-12-20 17:08:04 +00:00
Pax1601
b5f1a459c2 Update preload.js 2023-12-20 18:05:14 +01:00
Pax1601
6b12000979 Removed wrong await 2023-12-20 18:02:05 +01:00
Pax1601
1aec7f8081 Updated copy step during compilation 2023-12-20 17:39:25 +01:00
Pax1601
5f0e96e2e6 Update version.json 2023-12-20 17:25:25 +01:00
Pax1601
678a8585a9
Update build_package.yml 2023-12-20 17:24:32 +01:00
Pax1601
e632e379b6
Merge pull request #773 from Pax1601/Pax1601-patch-1
Update documentation.yml
2023-12-20 17:03:24 +01:00
Pax1601
1a7d2b5028
Update documentation.yml 2023-12-20 17:03:16 +01:00
Pax1601
ce28d49510
Merge pull request #763 from Pax1601/747-improve-configurator-for-automatic-saved-games-folder-detection
747 improve configurator for automatic saved games folder detection
2023-12-20 16:58:32 +01:00
Pax1601
0ac632cc9b
Merge branch 'main' into 747-improve-configurator-for-automatic-saved-games-folder-detection 2023-12-20 16:58:24 +01:00
Pax1601
47e4757b6e
Update defines.h 2023-12-20 16:57:14 +01:00
Pax1601
d21ee2a7b6
Update olympus.vcxproj 2023-12-20 16:56:43 +01:00
Pax1601
0cec61afea
Update luatools.vcxproj 2023-12-20 16:56:23 +01:00
Pax1601
ff04364178
Update logger.vcxproj 2023-12-20 16:55:20 +01:00
Pax1601
0cf2733d55
Update dcstools.vcxproj 2023-12-20 16:54:32 +01:00
Pax1601
f5319ed654
Update core.vcxproj 2023-12-20 16:52:41 +01:00
Pax1601
cfef9f4bc4 Minor refactoring 2023-12-20 16:42:30 +01:00
Pax1601
6abf7f059a
Merge pull request #738 from Dahlgren/ci/build-documentation-main
Only build documentation for main branch push
2023-12-20 16:32:04 +01:00
Pax1601
c0c1ff6e17
Merge pull request #752 from Pax1601/726-flight-level-is-three-digits-should-include-leading-zeros
FL now has three digits
2023-12-20 16:31:29 +01:00
Pax1601
856dba83a5
Merge pull request #753 from Pax1601/Shredmetal-patch-1
Shredmetal patch 1
2023-12-20 16:31:06 +01:00
Pax1601
2f37916595
Merge pull request #735 from LethalsLoaded/adapt-nomenclature
Fix login screen nomenclature
2023-12-20 16:30:44 +01:00
Pax1601
f36a29570b
Merge pull request #731 from Dahlgren/bugfix/case-sensitive-fs-paths
Fix wrong file paths for databases on case sensitive fs
2023-12-20 16:30:14 +01:00
Pax1601
62a3719163 Update package.json 2023-12-20 16:26:15 +01:00
Pax1601
e9511e9233 Update increase_version.js 2023-12-20 16:19:01 +01:00
Pax1601
51cf15b8cc Update notes.txt 2023-12-20 15:35:40 +01:00
Pax1601
278d0bdd3c Updated manager to allow updating 2023-12-20 15:34:55 +01:00
Pax1601
0a07f85fcf Added release notes file 2023-12-20 14:15:40 +01:00
Pax1601
7face05e12 Update logger.cpp 2023-12-20 14:08:49 +01:00
Pax1601
22ad5d5972 Small updates and moved log location to Log folder
Fixed logger error
2023-12-20 14:07:59 +01:00
Pax1601
2e194d557a Updated installations process 2023-12-20 12:41:05 +01:00
Pax1601
1a76df2056 Update increase_version.js 2023-12-20 12:35:01 +01:00
Pax1601
787bf13f3c Completed manager and moved client to common folder 2023-12-20 12:33:46 +01:00
Shredmetal
10f1c6a862
Added realistic Hornet Cap loadouts, formatted lua
Added: 2*AIM-9X, 2*AIM-120, 1*XT; 2*AIM-9X, 6*AIM-120, 2*XT.

Added indentations to lua file for readability
2023-12-20 15:36:52 +08:00
Shredmetal
0366cc38e2
Added realistic AA hornet loadouts to db
Added: 2*AIM-9X, 2*AIM-120, 1*XT; 2*AIM-9X, 6*AIM-120, 2*XT.
2023-12-20 15:35:32 +08:00
Pax1601
603018d1ef Added argument to vbs script 2023-12-19 18:39:35 +01:00
Pax1601
66ae06056b Created client app with electronc 2023-12-19 18:20:07 +01:00
Pax1601
17486ab40c Update increase_version.js
Update increase_version.js

Replaced back version
2023-12-19 14:49:32 +01:00
Pax1601
6cae91b06f Installer modified to not required DCS folder 2023-12-19 14:27:11 +01:00
Pax1601
9c055e0d71 Added olympus manager 2023-12-19 13:21:19 +01:00
Shredmetal
db4aeca47d
Update mod_ac_loadout_puller.py
removed extraneous comment
2023-12-19 18:48:13 +08:00
Shredmetal
c29a368e5a
Update mod_ac_loadout_puller.py 2023-12-19 18:44:01 +08:00
PeekabooSteam
dbe2442bb7 Added data, set list size limit 2023-12-18 20:52:15 +00:00
Shredmetal
2108fc4b26
mod aircraft loadout puller
python script to pull out loadouts from all installed mod aircraft into a lua file understandable by Olympus
2023-12-18 22:54:59 +08:00
PeekabooSteam
48f962ca4b Spawn history is functional 2023-12-18 12:57:44 +00:00
Pax1601
e80a5e8ca1 Added proxy middleware and demo backend app 2023-12-18 12:44:56 +01:00
PeekabooSteam
fb2ecc75eb FL now has three digits 2023-12-17 19:42:30 +00:00
Björn Dahlgren
ee95291418 Only build documentation for main branch push 2023-12-17 19:49:25 +01:00
Björn Dahlgren
46796fce13 CI workflow for client build on PRs 2023-12-17 19:46:32 +01:00
Andrzej Odwald
ee08f57abe - Fix nomenclature 2023-12-17 17:27:16 +00:00
Björn Dahlgren
eb86d8dfca Fix wrong file paths for databases on case sensitive fs 2023-12-17 17:28:57 +01:00
Pax1601
c75e20e58f
Update README.md 2023-12-17 08:58:05 +01:00
1831 changed files with 322438 additions and 146410 deletions

View File

@ -2,7 +2,7 @@ name: Build & package
on: on:
push: push:
branches: [ "main" ] branches: [ "main", "release-candidate" ]
permissions: permissions:
contents: read contents: read
@ -23,7 +23,7 @@ jobs:
vcpkg integrate install vcpkg integrate install
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v2 uses: actions/setup-node@v4
- name: Build - name: Build
working-directory: . working-directory: .
@ -31,8 +31,16 @@ jobs:
shell: cmd shell: cmd
- name: Upload a Build Artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v3.1.3 uses: actions/upload-artifact@v4.6.1
with: with:
name: latest name: development_build_not_a_release
path: installer/Output/*.exe path: ./package
- name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.1
with:
name: zip_only_package
path: ./zip
include-hidden-files: true

View File

@ -1,42 +0,0 @@
# ci.yml file for GitHub Actions
name: Documentation
on: [push]
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: write
pages: write
id-token: write
jobs:
build_docs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
- name: Install dependencies
run: npm ci
working-directory: ./client
- name: Create the docs directory locally in CI
run: npx typedoc --out ../docs/client @types/*.d.ts src/**/*.ts
working-directory: ./client
- name: Install Doxygen
run: sudo apt-get install doxygen -y
shell: bash
- name: Generate Doxygen Documentation
run: doxygen docs
shell: bash
working-directory: ./src
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: docs

52
.gitignore vendored
View File

@ -1,25 +1,45 @@
bin bin
.vs .vs
x64 x64
/src/vcpkg_installed
*.user
Output Output
*.aps
node_modules node_modules
/client/TODO.txt
/client/public/javascripts/bundle.js
!client/bin
/client/public/plugins
/client/plugins/controltips/index.js
hgt hgt
/client/public/databases/units/old
/client/plugins/databasemanager/index.js /backend/vcpkg_installed
/frontend/server/TODO.txt
/frontend/server/public/javascripts/bundle.js
/frontend/server/public/plugins
/frontend/server/plugins/controltips/index.js
/frontend/server/public/databases/units/old
/frontend/server/plugins/databasemanager/index.js
/src/html /src/html
/src/latex /src/latex
client/public/stylesheets/leaflet/leaflet-gesture-handling.css
client/public/javascripts/leaflet.nauticscale.js /package
client/public/javascripts/L.Path.Drag.js /build
/installer/archive/Scripts /DCS Olympus backups
/installer/archive/Mods /zip
/installer/installer/DCSOlympus*.exe
*.user
*.aps
L.Path.Drag.js
leaflet-gesture-handling.css
leaflet.nauticscale.js
leaflet.css
package-lock.json
!frontend/server/bin
/mock-dcs
/frontend/setup
frontend/server/public/plugins/controltipsplugin/index.js
frontend/website/plugins/controltips/index.js
/frontend/server/public/maps
*.pyc
/scripts/**/*.jpg
manager/manager.log
/frontend/server/public
/frontend/server/build
/frontend/react/.vite

BIN
DCS Olympus Manager.lnk Normal file

Binary file not shown.

59
INSTRUCTIONS.txt Normal file
View File

@ -0,0 +1,59 @@
_____ _____ _____ ____ _
| __ \ / ____|/ ____| / __ \| |
| | | | | | (___ | | | | |_ _ _ __ ___ _ __ _ _ ___
| | | | | \___ \ | | | | | | | | '_ ` _ \| '_ \| | | / __|
| |__| | |____ ____) | | |__| | | |_| | | | | | | |_) | |_| \__ \
|_____/ \_____|_____/ \____/|_|\__, |_| |_| |_| .__/ \__,_|___/
__/ | | |
|___/ |_|
{{OLYMPUS_VERSION_NUMBER}}
==========================================
INSTALLATION INSTRUCTIONS
1) Close any applications which may interfere with installation, including Digital Combat Simulator (DCS) and previous versions of Olympus.
2) If you DO NOT have Olympus already installed, SKIP THIS STEP. If you have already installed Olympus, do the following:
NOTE: If you made any changes to your unit databases or mods.lua file (e.g. to support a third party mod) make a backup of the edited files before proceeding or changes will be lost;
a) If you installed DCS Olympus v1.0.3 using the installer, simply remove it using Windows's "Add or remove programs" application.
b) If you installed DCS Olympus v1.0.3 using the archived version, remove it by deleting the "...<DCS Saved Games folder>\Mods\Services\Olympus" folder. Do this for every DCS instance you installed Olympus in.
Remember to delete any shortcuts you created. Don't worry, they will be created automatically again by the installation script provided in this package.
3) Create a folder named "DCS Olympus" in your "Saved Games" directory and extract all the contents of the downloaded package into it.
NOTE:
a) Do not extract the contents of the package directly in your Saved Games folder or in your DCS Saved Games folder.
b) Unlike previous version of Olympus, it is no longer necessary to copy the packaged files into each DCS instance folder.
4) Execute the "installer.bat" script by double-clicking on it. It is located in the folder you created in step 3. Wait for the installation script to complete. Installation may take a couple of minutes, after which the Manager will start automatically.
NOTE: depending on your Windows configuration, the script may be called "installer" (without .bat at the end).
5) The Olympus Manager will open. This will allow you to add/remove Olympus to individual DCS instances.
Use the Olympus Manager and follow the instructions to install and setup Olympus.
6) Start DCS and run a mission. Make sure it is UNPAUSED.
7) Open Olympus via the shortcut and login using any username and the Game Master password set using the Manager. (NOTE: not your DCS server password).
Local installation: run the client from the provided desktop shortcut or start it using the "View and manage instances" page of the Manager.
Dedicated server: users must first start the Olympus server from the provided desktop shortcut or using the "View and manage instances" page of the Manager.
Then log in using any browser and visiting "http:\\<server IP>:<frontend port>" (frontend port is 3000 by default, but can be edited using the Manager)
8) You can use the manager at any time to change the ports and/or passwords. If you do, REMEMBER TO RESTART OLYMPUS AND DCS.
NOTES:
a) when launching the Manager you will be prompted to allow Electron to create a firewall rule. This is optional and can be denied without effect on the operation of the Manager;
b) if you are using Olympus on a dedicated server with a router, you must enable port forwarding on the frontend port (3000 by default);
c) unlike Olympus v1.0.3, running the netsh command is no longer required. It is also no longer required to create firewall rules or port forwarding for the backend port. (Optional) If you already performed this steps in the past you can delete the firewall and netsh rules.
==========================================
UPDATING INSTRUCTIONS
IF YOU ARE UPDATING FROM DCS OLYMPUS v1.0.3, FOLLOW THE "INSTALLATION INSTRUCTIONS".
To update your Olympus installation you have two options:
a) download the new package from the GitHub releases page, delete the old unpacked package folder, then follow the INSTALLATION INSTRUCTIONS;
b) run the Olympus Manager. If an update is available you will be given the option to automatically update Olympus from there.
For either options a) or b), remember to close any applications which may interfere with installation, including Digital Combat Simulator (DCS) and previous versions of Olympus.

View File

@ -1,4 +1,3 @@
## Important note: DCS Olympus is in beta state. No official release has been produced yet. The first public version is planned for mid december 2023.
<img align="left" width="30" src="https://github.com/Pax1601/DCSOlympus/assets/103559271/0ecff279-a87c-4e2d-a4c7-da98c74adf38"> <img align="left" width="30" src="https://github.com/Pax1601/DCSOlympus/assets/103559271/0ecff279-a87c-4e2d-a4c7-da98c74adf38">
[**Join our Discord**](https://discord.gg/kNAQkhUHnQ) [**Join our Discord**](https://discord.gg/kNAQkhUHnQ)
@ -10,8 +9,6 @@
# DCS Olympus # DCS Olympus
![alt text](https://github.com/Pax1601/DCSOlympus/blob/main/client/sample.png?raw=true)
### What is this? ### What is this?
DCS: Olympus is a free and open-source mod for DCS that enables dynamic real-time control through a map interface. The user is able to spawn units/groups, deploy a variety of effects such as smoke, flares, or explosions, and waypoints/tasks can be given to AI units in real-time in a way similar to a classic RTS game. DCS: Olympus is a free and open-source mod for DCS that enables dynamic real-time control through a map interface. The user is able to spawn units/groups, deploy a variety of effects such as smoke, flares, or explosions, and waypoints/tasks can be given to AI units in real-time in a way similar to a classic RTS game.
@ -24,18 +21,28 @@ Even better it requires no client mods be installed if used on a server
The full feature list is simply too long to enumerate in a short summary but needless to say Olympus offers up a lot of unique gameplay that has previously not existed, and enhances many other elements of DCS in exciting ways The full feature list is simply too long to enumerate in a short summary but needless to say Olympus offers up a lot of unique gameplay that has previously not existed, and enhances many other elements of DCS in exciting ways
### Installing DCS Olympus ### Installing DCS Olympus
A prebuilt installer will soon be released and available here Check the [Wiki](https://github.com/Pax1601/DCSOlympus/wiki) for installation instructions
# Frequently Asked Questions # Frequently Asked Questions
### Can I join up and help out with the project? ###
We are currently running towards first release in the very near future so we are not looking to add more people to the core team for the moment. However that does not mean we are not open to collaborations and help going forward, if you want to help for now we are committed to the free and open source model so feel free to check out the github, familiarize yourself with the project and maybe even start submitting pull requests for open issues.
Post-release we will be more interested in developing partnerships/collaborations with other teams/projects and potentially bringing in more team members, we will update this after release on how that will be managed! ### I need troubleshooting guidance, please help? ###
Read through the [Installation Guide](https://github.com/Pax1601/DCSOlympus/wiki) to ensure you have setup Olympus correctly.
Read through [Setup Troubleshooting](https://github.com/Pax1601/DCSOlympus/wiki/3.-Setup-FAQ-and-Troubleshooting) for common issues and solutions.
If you're still having issues after trying the steps above, please post in the community-support channel with the following:
A detailed description of your issue
Your Olympus log file \user home folder\AppData\Local\Temp\Olympus_log.txt for some it might be in \DCS Saved Games folder\Logs\Olympus_log.txt
Your DCS log file \DCS Saved Games folder\Logs\dcs.log
Screenshots of any relevant screens or issues and any other pertinent information.
### Can I join up and help out with the project? ###
Absolutely, join the discord and ping any of the developers to get briefed.
### Can I be a beta/alpha-tester? ### ### Can I be a beta/alpha-tester? ###
With first public release planned for the very-near future we are fully committed to the final sprint, as such we will not be formally recruiting more people to test pre-release. Same as above!
Post-release we will be eager to hear feedback of all forms and take in bug-reports, at this time after release we will begin considering bringing in more team members to test in development versions as we go.
### Do you have a roadmap? ### ### Do you have a roadmap? ###
We do not have a roadmap no, we have a laundry list of things we are hoping to do. We do not have a roadmap no, we have a laundry list of things we are hoping to do.
@ -72,9 +79,5 @@ A and B never communicate when you connect the client you download the web page
Olympus by itself should not have a noticeable impact on server performance, however the ability for the user to spawn arbitrary units and command engagements means Olympus can be used in such a way that brings the game to it's knees. Olympus by itself should not have a noticeable impact on server performance, however the ability for the user to spawn arbitrary units and command engagements means Olympus can be used in such a way that brings the game to it's knees.
Be cognizant of how you play, whether it's done through Olympus or the mission editor 500 MLRS units firing at once is not going to go over well with most servers Be cognizant of how you play, whether it's done through Olympus or the mission editor 500 MLRS units firing at once is not going to go over well with most servers

View File

@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 FILEVERSION 2,0,0,0
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -79,12 +79,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "DCS Olympus" VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus" VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "core.dll" VALUE "InternalName", "core.dll"
VALUE "LegalCopyright", "Copyright (C) 2023" VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "core.dll" VALUE "OriginalFilename", "core.dll"
VALUE "ProductName", "DCS Olympus" VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "ProductVersion", "2.0.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -110,26 +110,26 @@
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir> <OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir> <OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>

View File

@ -18,6 +18,12 @@ public:
virtual void changeSpeed(string change) = 0; virtual void changeSpeed(string change) = 0;
virtual void changeAltitude(string change) = 0; virtual void changeAltitude(string change) = 0;
virtual double getDestinationReachedThreshold() { return AIR_DEST_DIST_THR; } virtual double getDestinationReachedThreshold() { return AIR_DEST_DIST_THR; }
virtual void setRacetrackLength(double newValue);
virtual void setRacetrackAnchor(Coords newValue);
virtual void setRacetrackBearing(double newValue);
virtual void setCargoWeight(double newValue);
protected: protected:
virtual void AIloop(); virtual void AIloop();

View File

@ -5,6 +5,11 @@
#include "logger.h" #include "logger.h"
#include "datatypes.h" #include "datatypes.h"
struct CommandResult {
string hash;
string result;
};
namespace CommandPriority { namespace CommandPriority {
enum CommandPriorities { LOW, MEDIUM, HIGH, IMMEDIATE }; enum CommandPriorities { LOW, MEDIUM, HIGH, IMMEDIATE };
}; };
@ -18,6 +23,7 @@ namespace SetCommandType {
FORMATION = 5, FORMATION = 5,
RTB_ON_BINGO = 6, RTB_ON_BINGO = 6,
SILENCE = 7, SILENCE = 7,
ALARM_STATE = 9,
RTB_ON_OUT_OF_AMMO = 10, RTB_ON_OUT_OF_AMMO = 10,
ECM_USING = 13, ECM_USING = 13,
PROHIBIT_AA = 14, PROHIBIT_AA = 14,
@ -45,6 +51,14 @@ namespace ROE {
}; };
} }
namespace AlarmState {
enum AlarmStates {
AUTO = 0,
GREEN = 1,
RED = 2,
};
}
namespace ReactionToThreat { namespace ReactionToThreat {
enum ReactionsToThreat { enum ReactionsToThreat {
NO_REACTION = 0, NO_REACTION = 0,
@ -430,3 +444,138 @@ private:
const unsigned int intensity; const unsigned int intensity;
const string explosionType; const string explosionType;
}; };
/* Shine a laser with a specific code */
class FireLaser : public Command
{
public:
FireLaser(unsigned int ID, unsigned int code, Coords destination, function<void(void)> callback = []() {}) :
Command(callback),
ID(ID),
destination(destination),
code(code)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const unsigned int ID;
const unsigned int code;
const Coords destination;
};
/* Shine a infrared light */
class FireInfrared : public Command
{
public:
FireInfrared(unsigned int ID, Coords destination, function<void(void)> callback = []() {}) :
Command(callback),
ID(ID),
destination(destination)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const unsigned int ID;
const Coords destination;
};
/* Change a laser code */
class SetLaserCode : public Command
{
public:
SetLaserCode(unsigned int spotID, unsigned int code, function<void(void)> callback = []() {}) :
Command(callback),
spotID(spotID),
code(code)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const unsigned int spotID;
const unsigned int code;
};
/* Delete a spot code */
class DeleteSpot : public Command
{
public:
DeleteSpot(unsigned int spotID, function<void(void)> callback = []() {}) :
Command(callback),
spotID(spotID)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const unsigned int spotID;
};
/* Move spot to a new target */
class MoveSpot : public Command
{
public:
MoveSpot(unsigned int spotID, Coords destination, function<void(void)> callback = []() {}) :
Command(callback),
spotID(spotID),
destination(destination)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const unsigned int spotID;
const Coords destination;
};
/* Set cargo weight */
class SetCargoWeight : public Command
{
public:
SetCargoWeight(unsigned int ID, double weight, function<void(void)> callback = []() {}) :
Command(callback),
ID(ID),
weight(weight)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const unsigned int ID;
const double weight;
};
/* Register draw argument */
class RegisterDrawArgument : public Command
{
public:
RegisterDrawArgument(unsigned int ID, unsigned int argument, bool active, function<void(void)> callback = []() {}) :
Command(callback),
ID(ID),
argument(argument),
active(active)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const unsigned int ID;
const unsigned int argument;
const bool active;
};

View File

@ -7,12 +7,17 @@ namespace DataIndex {
startOfData = 0, startOfData = 0,
category, category,
alive, alive,
alarmState,
radarState,
human, human,
controlled, controlled,
coalition, coalition,
country, country,
name, name,
unitName, unitName,
callsign,
unitID,
groupID,
groupName, groupName,
state, state,
task, task,
@ -50,6 +55,25 @@ namespace DataIndex {
shotsScatter, shotsScatter,
shotsIntensity, shotsIntensity,
health, health,
racetrackLength,
racetrackAnchor,
racetrackBearing,
timeToNextTasking,
barrelHeight,
muzzleVelocity,
aimTime,
shotsToFire,
shotsBaseInterval,
shotsBaseScatter,
engagementRange,
targetingRange,
aimMethodRange,
acquisitionRange,
airborne,
cargoWeight,
drawArguments,
customString,
customInteger,
lastIndex, lastIndex,
endOfData = 255 endOfData = 255
}; };
@ -139,6 +163,11 @@ namespace DataTypes {
unsigned int ID = 0; unsigned int ID = 0;
unsigned char detectionMethod = 0; unsigned char detectionMethod = 0;
}; };
struct DrawArgument {
unsigned int argument = 0;
double value = 0.0;
};
} }
#pragma pack(pop) #pragma pack(pop)
@ -147,12 +176,16 @@ bool operator==(const DataTypes::Radio& lhs, const DataTypes::Radio& rhs);
bool operator==(const DataTypes::GeneralSettings& lhs, const DataTypes::GeneralSettings& rhs); bool operator==(const DataTypes::GeneralSettings& lhs, const DataTypes::GeneralSettings& rhs);
bool operator==(const DataTypes::Ammo& lhs, const DataTypes::Ammo& rhs); bool operator==(const DataTypes::Ammo& lhs, const DataTypes::Ammo& rhs);
bool operator==(const DataTypes::Contact& lhs, const DataTypes::Contact& rhs); bool operator==(const DataTypes::Contact& lhs, const DataTypes::Contact& rhs);
bool operator==(const DataTypes::DrawArgument& lhs, const DataTypes::DrawArgument& rhs);
struct SpawnOptions { struct SpawnOptions {
string unitType; string unitType;
Coords location; Coords location;
string loadout; string loadout;
string skill;
string liveryID; string liveryID;
double heading;
string payload;
}; };
struct CloneOptions { struct CloneOptions {

View File

@ -17,7 +17,7 @@ public:
virtual void setOnOff(bool newOnOff, bool force = false); virtual void setOnOff(bool newOnOff, bool force = false);
virtual void setFollowRoads(bool newFollowRoads, bool force = false); virtual void setFollowRoads(bool newFollowRoads, bool force = false);
void aimAtPoint(Coords aimTarget); string aimAtPoint(Coords aimTarget);
protected: protected:
virtual void AIloop(); virtual void AIloop();

View File

@ -13,7 +13,14 @@ public:
void execute(lua_State* L); void execute(lua_State* L);
void handleRequest(string key, json::value value, string username, json::value& answer); void handleRequest(string key, json::value value, string username, json::value& answer);
bool checkSpawnPoints(int spawnPoints, string coalition); bool checkSpawnPoints(int spawnPoints, string coalition);
bool isCommandExecuted(string commandHash) { return (find(executedCommandsHashes.begin(), executedCommandsHashes.end(), commandHash) != executedCommandsHashes.end()); } bool isCommandExecuted(string commandHash) {
for (auto& commandResult : executedCommandResults) {
if (commandResult.hash == commandHash) {
return true;
}
}
return false;
}
void setFrameRate(double newFrameRate) { frameRate = newFrameRate; } void setFrameRate(double newFrameRate) { frameRate = newFrameRate; }
void setRestrictSpawns(bool newRestrictSpawns) { restrictSpawns = newRestrictSpawns; } void setRestrictSpawns(bool newRestrictSpawns) { restrictSpawns = newRestrictSpawns; }
@ -36,7 +43,7 @@ public:
private: private:
list<Command*> commands; list<Command*> commands;
list<string> executedCommandsHashes; list<CommandResult> executedCommandResults;
unsigned int load = 0; unsigned int load = 0;
double frameRate = 0; double frameRate = 0;

View File

@ -19,12 +19,12 @@ public:
~Unit(); ~Unit();
/********** Methods **********/ /********** Methods **********/
void initialize(json::value json); virtual void initialize(json::value json) final;
virtual void setDefaults(bool force = false); virtual void setDefaults(bool force = false);
void runAILoop(); void runAILoop();
void update(json::value json, double dt); virtual void update(json::value json, double dt) final;
void refreshLeaderData(unsigned long long time); void refreshLeaderData(unsigned long long time);
unsigned int getID() { return ID; } unsigned int getID() { return ID; }
@ -62,15 +62,21 @@ public:
bool hasFreshData(unsigned long long time); bool hasFreshData(unsigned long long time);
bool checkFreshness(unsigned char datumIndex, unsigned long long time); bool checkFreshness(unsigned char datumIndex, unsigned long long time);
unsigned int computeTotalAmmo();
/********** Setters **********/ /********** Setters **********/
virtual void setCategory(string newValue) { updateValue(category, newValue, DataIndex::category); } virtual void setCategory(string newValue) { updateValue(category, newValue, DataIndex::category); }
virtual void setAlive(bool newValue) { updateValue(alive, newValue, DataIndex::alive); } virtual void setAlive(bool newValue) { updateValue(alive, newValue, DataIndex::alive); }
virtual void setAlarmState(unsigned char newValue, bool force = false);
virtual void setHuman(bool newValue) { updateValue(human, newValue, DataIndex::human); } virtual void setHuman(bool newValue) { updateValue(human, newValue, DataIndex::human); }
virtual void setControlled(bool newValue) { updateValue(controlled, newValue, DataIndex::controlled); } virtual void setControlled(bool newValue) { updateValue(controlled, newValue, DataIndex::controlled); }
virtual void setCoalition(unsigned char newValue) { updateValue(coalition, newValue, DataIndex::coalition); } virtual void setCoalition(unsigned char newValue) { updateValue(coalition, newValue, DataIndex::coalition); }
virtual void setCountry(unsigned char newValue) { updateValue(country, newValue, DataIndex::country); } virtual void setCountry(unsigned char newValue) { updateValue(country, newValue, DataIndex::country); }
virtual void setName(string newValue) { updateValue(name, newValue, DataIndex::name); } virtual void setName(string newValue) { updateValue(name, newValue, DataIndex::name); }
virtual void setUnitName(string newValue) { updateValue(unitName, newValue, DataIndex::unitName); } virtual void setUnitName(string newValue) { updateValue(unitName, newValue, DataIndex::unitName); }
virtual void setCallsign(string newValue) { updateValue(callsign, newValue, DataIndex::callsign); }
virtual void setUnitID(unsigned int newValue) { updateValue(unitID, newValue, DataIndex::unitID); }
virtual void setGroupID(unsigned int newValue) { updateValue(groupID, newValue, DataIndex::groupID); }
virtual void setGroupName(string newValue) { updateValue(groupName, newValue, DataIndex::groupName); } virtual void setGroupName(string newValue) { updateValue(groupName, newValue, DataIndex::groupName); }
virtual void setState(unsigned char newValue) { updateValue(state, newValue, DataIndex::state); }; virtual void setState(unsigned char newValue) { updateValue(state, newValue, DataIndex::state); };
virtual void setTask(string newValue) { updateValue(task, newValue, DataIndex::task); } virtual void setTask(string newValue) { updateValue(task, newValue, DataIndex::task); }
@ -108,17 +114,41 @@ public:
virtual void setShotsScatter(unsigned char newValue) { updateValue(shotsScatter, newValue, DataIndex::shotsScatter); } virtual void setShotsScatter(unsigned char newValue) { updateValue(shotsScatter, newValue, DataIndex::shotsScatter); }
virtual void setShotsIntensity(unsigned char newValue) { updateValue(shotsIntensity, newValue, DataIndex::shotsIntensity); } virtual void setShotsIntensity(unsigned char newValue) { updateValue(shotsIntensity, newValue, DataIndex::shotsIntensity); }
virtual void setHealth(unsigned char newValue) { updateValue(health, newValue, DataIndex::health); } virtual void setHealth(unsigned char newValue) { updateValue(health, newValue, DataIndex::health); }
virtual void setRacetrackLength(double newValue) { updateValue(racetrackLength, newValue, DataIndex::racetrackLength); }
virtual void setRacetrackAnchor(Coords newValue) { updateValue(racetrackAnchor, newValue, DataIndex::racetrackAnchor); }
virtual void setRacetrackBearing(double newValue) { updateValue(racetrackBearing, newValue, DataIndex::racetrackBearing); }
virtual void setTimeToNextTasking(double newValue) { updateValue(timeToNextTasking, newValue, DataIndex::timeToNextTasking); }
virtual void setBarrelHeight(double newValue) { updateValue(barrelHeight, newValue, DataIndex::barrelHeight); }
virtual void setMuzzleVelocity(double newValue) { updateValue(muzzleVelocity, newValue, DataIndex::muzzleVelocity); }
virtual void setAimTime(double newValue) { updateValue(aimTime, newValue, DataIndex::aimTime); }
virtual void setShotsToFire(unsigned int newValue) { updateValue(shotsToFire, newValue, DataIndex::shotsToFire); }
virtual void setShotsBaseInterval(double newValue) { updateValue(shotsBaseInterval, newValue, DataIndex::shotsBaseInterval); }
virtual void setShotsBaseScatter(double newValue) { updateValue(shotsBaseScatter, newValue, DataIndex::shotsBaseScatter); }
virtual void setEngagementRange(double newValue) { updateValue(engagementRange, newValue, DataIndex::engagementRange); }
virtual void setTargetingRange(double newValue) { updateValue(targetingRange, newValue, DataIndex::targetingRange); }
virtual void setAimMethodRange(double newValue) { updateValue(aimMethodRange, newValue, DataIndex::aimMethodRange); }
virtual void setAcquisitionRange(double newValue) { updateValue(acquisitionRange, newValue, DataIndex::acquisitionRange); }
virtual void setRadarState(bool newValue) { updateValue(radarState, newValue, DataIndex::radarState); }
virtual void setAirborne(bool newValue) { updateValue(airborne, newValue, DataIndex::airborne); }
virtual void setCargoWeight(double newValue) { updateValue(cargoWeight, newValue, DataIndex::cargoWeight); }
virtual void setDrawArguments(vector<DataTypes::DrawArgument> newValue);
virtual void setCustomString(string newValue) { updateValue(customString, newValue, DataIndex::customString); }
virtual void setCustomInteger(unsigned long newValue) { updateValue(customInteger, newValue, DataIndex::customInteger); }
/********** Getters **********/ /********** Getters **********/
virtual string getCategory() { return category; }; virtual string getCategory() { return category; }
virtual bool getAlive() { return alive; } virtual bool getAlive() { return alive; }
virtual unsigned char getAlarmState() { return alarmState; }
virtual bool getHuman() { return human; } virtual bool getHuman() { return human; }
virtual bool getControlled() { return controlled; } virtual bool getControlled() { return controlled; }
virtual unsigned char getCoalition() { return coalition; } virtual unsigned char getCoalition() { return coalition; }
virtual unsigned char getCountry() { return country; } virtual unsigned char getCountry() { return country; }
virtual string getName() { return name; } virtual string getName() { return name; }
virtual string getCallsign() { return callsign; }
virtual string getUnitName() { return unitName; } virtual string getUnitName() { return unitName; }
virtual string getGroupName() { return groupName; } virtual string getGroupName() { return groupName; }
virtual unsigned int getUnitID() { return unitID; }
virtual unsigned int getGroupID() { return groupID; }
virtual unsigned char getState() { return state; } virtual unsigned char getState() { return state; }
virtual string getTask() { return task; } virtual string getTask() { return task; }
virtual bool getHasTask() { return hasTask; } virtual bool getHasTask() { return hasTask; }
@ -155,6 +185,26 @@ public:
virtual unsigned char getShotsScatter() { return shotsScatter; } virtual unsigned char getShotsScatter() { return shotsScatter; }
virtual unsigned char getShotsIntensity() { return shotsIntensity; } virtual unsigned char getShotsIntensity() { return shotsIntensity; }
virtual unsigned char getHealth() { return health; } virtual unsigned char getHealth() { return health; }
virtual double getRacetrackLength() { return racetrackLength; }
virtual Coords getRacetrackAnchor() { return racetrackAnchor; }
virtual double getRacetrackBearing() { return racetrackBearing; }
virtual double getTimeToNextTasking() { return timeToNextTasking; }
virtual double getBarrelHeight() { return barrelHeight; }
virtual double getMuzzleVelocity() { return muzzleVelocity; }
virtual double getAimTime() { return aimTime; }
virtual unsigned int getShotsToFire() { return shotsToFire; }
virtual double getShotsBaseInterval() { return shotsBaseInterval; }
virtual double getShotsBaseScatter() { return shotsBaseScatter; }
virtual double getEngagementRange() { return engagementRange; }
virtual double getTargetingRange() { return targetingRange; }
virtual double getAimMethodRange() { return aimMethodRange; }
virtual double getAcquisitionRange() { return acquisitionRange; }
virtual bool getRadarState() { return radarState; }
virtual bool getAirborne() { return airborne; }
virtual double getCargoWeight() { return cargoWeight; }
virtual vector<DataTypes::DrawArgument> getDrawArguments() { return drawArguments; }
virtual string getCustomString() { return customString; }
virtual unsigned long getCustomInteger() { return customInteger; }
protected: protected:
unsigned int ID; unsigned int ID;
@ -167,8 +217,13 @@ protected:
unsigned char country = NULL; unsigned char country = NULL;
string name = ""; string name = "";
string unitName = ""; string unitName = "";
string callsign = "";
unsigned int unitID = NULL;
unsigned int groupID = NULL;
string groupName = ""; string groupName = "";
unsigned char state = State::NONE; unsigned char state = State::NONE;
unsigned char alarmState = AlarmState::AUTO;
bool radarState = false;
string task = ""; string task = "";
bool hasTask = false; bool hasTask = false;
Coords position = Coords(NULL); Coords position = Coords(NULL);
@ -187,10 +242,13 @@ protected:
double desiredAltitude = 1; double desiredAltitude = 1;
bool desiredAltitudeType = 0; /* ASL */ bool desiredAltitudeType = 0; /* ASL */
unsigned int leaderID = NULL; unsigned int leaderID = NULL;
double racetrackLength = NULL;
Coords racetrackAnchor = Coords(NULL);
double racetrackBearing = NULL;
Offset formationOffset = Offset(NULL); Offset formationOffset = Offset(NULL);
unsigned int targetID = NULL; unsigned int targetID = NULL;
Coords targetPosition = Coords(NULL); Coords targetPosition = Coords(NULL);
unsigned char ROE = ROE::OPEN_FIRE_WEAPON_FREE; unsigned char ROE = ROE::OPEN_FIRE;
unsigned char reactionToThreat = ReactionToThreat::EVADE_FIRE; unsigned char reactionToThreat = ReactionToThreat::EVADE_FIRE;
unsigned char emissionsCountermeasures = EmissionCountermeasure::DEFEND; unsigned char emissionsCountermeasures = EmissionCountermeasure::DEFEND;
DataTypes::TACAN TACAN; DataTypes::TACAN TACAN;
@ -205,16 +263,36 @@ protected:
unsigned char shotsScatter = 2; unsigned char shotsScatter = 2;
unsigned char shotsIntensity = 2; unsigned char shotsIntensity = 2;
unsigned char health = 100; unsigned char health = 100;
double timeToNextTasking = 0;
double barrelHeight = 0;
double muzzleVelocity = 0;
double aimTime = 0;
unsigned int shotsToFire = 0;
double shotsBaseInterval = 0;
double shotsBaseScatter = 0;
double engagementRange = 0;
double targetingRange = 0;
double aimMethodRange = 0;
double acquisitionRange = 0;
bool airborne = false;
double cargoWeight = 0;
vector<DataTypes::DrawArgument> drawArguments;
string customString = "";
unsigned long customInteger = 0;
/********** Other **********/ /********** Other **********/
unsigned int taskCheckCounter = 0; unsigned int taskCheckCounter = 0;
unsigned int internalCounter = 0;
Unit* missOnPurposeTarget = nullptr; Unit* missOnPurposeTarget = nullptr;
bool hasTaskAssigned = false; bool hasTaskAssigned = false;
double initialFuel = 0; double initialFuel = 0;
map<unsigned char, unsigned long long> updateTimeMap; map<unsigned char, unsigned long long> updateTimeMap;
unsigned long long lastLoopTime = 0; unsigned long long lastLoopTime = 0;
bool enableTaskFailedCheck = false; bool enableTaskFailedCheck = false;
unsigned long nextTaskingMilliseconds = 0;
unsigned int totalShellsFired = 0;
unsigned int shellsFiredAtTasking = 0;
unsigned int oldAmmo = 0;
/********** Private methods **********/ /********** Private methods **********/
virtual void AIloop() = 0; virtual void AIloop() = 0;

View File

@ -23,8 +23,8 @@ public:
void deleteUnit(unsigned int ID, bool explosion, string explosionType, bool immediate); void deleteUnit(unsigned int ID, bool explosion, string explosionType, bool immediate);
void acquireControl(unsigned int ID); void acquireControl(unsigned int ID);
void loadDatabases(); void loadDatabases();
Unit* getClosestUnit(Unit* unit, unsigned char coalition, vector<string> categories, double &distance); Unit* getClosestUnit(Unit* unit, unsigned char coalition, vector<string> categories, double &distance, bool airborneOnly = true);
map<Unit*, double> getUnitsInRange(Unit* unit, unsigned char coalition, vector<string> categories, double range); map<Unit*, double> getUnitsInRange(Unit* unit, unsigned char coalition, vector<string> categories, double range, bool airborneOnly = true);
private: private:
map<unsigned int, Unit*> units; map<unsigned int, Unit*> units;

View File

@ -113,4 +113,10 @@ class Bomb : public Weapon
{ {
public: public:
Bomb(json::value json, unsigned int ID); Bomb(json::value json, unsigned int ID);
};
class Shell : public Weapon
{
public:
Shell(json::value json, unsigned int ID);
}; };

View File

@ -154,6 +154,13 @@ void AirUnit::AIloop()
{ {
srand(static_cast<unsigned int>(time(NULL)) + ID); srand(static_cast<unsigned int>(time(NULL)) + ID);
/* Reset the anchor */
if (state != State::IDLE) {
setRacetrackAnchor(Coords(NULL));
setRacetrackBearing(NULL);
setRacetrackLength(NULL);
}
/* State machine */ /* State machine */
switch (state) { switch (state) {
case State::IDLE: { case State::IDLE: {
@ -166,21 +173,27 @@ void AirUnit::AIloop()
if (!getHasTask()) if (!getHasTask())
{ {
if (racetrackAnchor == Coords(NULL)) setRacetrackAnchor(position);
if (racetrackBearing == NULL) setRacetrackBearing(heading);
std::ostringstream taskSS; std::ostringstream taskSS;
if (isActiveTanker) { if (isActiveTanker) {
taskSS << "{ [1] = { id = 'Tanker' }, [2] = { id = 'Orbit', pattern = 'Race-Track', altitude = " << taskSS << "{ [1] = { id = 'Tanker' }, [2] = { id = 'Orbit', pattern = 'Race-Track', altitude = " <<
desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitude << ", lat = " << racetrackAnchor.lat << ", lng = " << racetrackAnchor.lng << ", speed = " << desiredSpeed << ", altitudeType = '" <<
(desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "' }}"; (desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "', heading = " <<
racetrackBearing << ", length = " << (racetrackLength != NULL ? racetrackLength : (50000 * 1.852)) << " }}";
} }
else if (isActiveAWACS) { else if (isActiveAWACS) {
taskSS << "{ [1] = { id = 'AWACS' }, [2] = { id = 'Orbit', pattern = 'Circle', altitude = " << taskSS << "{ [1] = { id = 'AWACS' }, [2] = { id = 'Orbit', pattern = 'Race-Track', altitude = " <<
desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitude << ", lat = " << racetrackAnchor.lat << ", lng = " << racetrackAnchor.lng << ", speed = " << desiredSpeed << ", altitudeType = '" <<
(desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "' }}"; (desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "', heading = " <<
racetrackBearing << ", length = " << (racetrackLength != NULL ? racetrackLength : (desiredSpeed * 30)) << " }}";
} }
else { else {
taskSS << "{ id = 'Orbit', pattern = 'Circle', altitude = " << taskSS << "{ id = 'Orbit', pattern = 'Race-Track', altitude = " <<
desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitude << ", lat = " << racetrackAnchor.lat << ", lng = " << racetrackAnchor.lng << ", speed = " << desiredSpeed << ", altitudeType = '" <<
(desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "'}"; (desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "', heading = " <<
racetrackBearing << ", length = " << (racetrackLength != NULL ? racetrackLength: (desiredSpeed * 30)) << " }";
} }
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); })); Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command); scheduler->appendCommand(command);
@ -376,4 +389,53 @@ void AirUnit::AIloop()
default: default:
break; break;
} }
}
void AirUnit::setRacetrackLength(double newRacetrackLength) {
if (racetrackLength != newRacetrackLength) {
racetrackLength = newRacetrackLength;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::racetrackLength);
}
}
void AirUnit::setRacetrackAnchor(Coords newRacetrackAnchor) {
if (racetrackAnchor != newRacetrackAnchor) {
racetrackAnchor = newRacetrackAnchor;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::racetrackAnchor);
}
}
void AirUnit::setRacetrackBearing(double newRacetrackBearing) {
if (racetrackBearing != newRacetrackBearing) {
racetrackBearing = newRacetrackBearing;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::racetrackBearing);
}
}
void AirUnit::setCargoWeight(double newCargoWeight) {
if (cargoWeight != newCargoWeight) {
cargoWeight = newCargoWeight;
triggerUpdate(DataIndex::cargoWeight);
Command* command = dynamic_cast<Command*>(new SetCargoWeight(this->ID, cargoWeight));
scheduler->appendCommand(command);
}
} }

View File

@ -46,7 +46,9 @@ string SpawnGroundUnits::getString()
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", " << "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
<< "lat = " << spawnOptions[i].location.lat << ", " << "lat = " << spawnOptions[i].location.lat << ", "
<< "lng = " << spawnOptions[i].location.lng << ", " << "lng = " << spawnOptions[i].location.lng << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << " }, "; << "heading = " << spawnOptions[i].heading << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
} }
std::ostringstream commandSS; std::ostringstream commandSS;
@ -56,6 +58,7 @@ string SpawnGroundUnits::getString()
<< "coalition = " << "\"" << coalition << "\"" << ", " << "coalition = " << "\"" << coalition << "\"" << ", "
<< "country = \"" << country << "\", " << "country = \"" << country << "\", "
<< "units = " << "{" << unitsSS.str() << "}" << "}"; << "units = " << "{" << unitsSS.str() << "}" << "}";
commandSS << ", \"" << this->getHash() << "\"";
return commandSS.str(); return commandSS.str();
} }
@ -70,7 +73,9 @@ string SpawnNavyUnits::getString()
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", " << "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
<< "lat = " << spawnOptions[i].location.lat << ", " << "lat = " << spawnOptions[i].location.lat << ", "
<< "lng = " << spawnOptions[i].location.lng << ", " << "lng = " << spawnOptions[i].location.lng << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << " }, "; << "heading = " << spawnOptions[i].heading << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
} }
std::ostringstream commandSS; std::ostringstream commandSS;
@ -80,6 +85,7 @@ string SpawnNavyUnits::getString()
<< "coalition = " << "\"" << coalition << "\"" << ", " << "coalition = " << "\"" << coalition << "\"" << ", "
<< "country = \"" << country << "\", " << "country = \"" << country << "\", "
<< "units = " << "{" << unitsSS.str() << "}" << "}"; << "units = " << "{" << unitsSS.str() << "}" << "}";
commandSS << ", \"" << this->getHash() << "\"";
return commandSS.str(); return commandSS.str();
} }
@ -94,8 +100,11 @@ string SpawnAircrafts::getString()
<< "lat = " << spawnOptions[i].location.lat << ", " << "lat = " << spawnOptions[i].location.lat << ", "
<< "lng = " << spawnOptions[i].location.lng << ", " << "lng = " << spawnOptions[i].location.lng << ", "
<< "alt = " << spawnOptions[i].location.alt << ", " << "alt = " << spawnOptions[i].location.alt << ", "
<< "heading = " << spawnOptions[i].heading << ", "
<< "loadout = \"" << spawnOptions[i].loadout << "\"" << ", " << "loadout = \"" << spawnOptions[i].loadout << "\"" << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << " }, "; << "payload = " << spawnOptions[i].payload << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
} }
std::ostringstream commandSS; std::ostringstream commandSS;
@ -106,6 +115,7 @@ string SpawnAircrafts::getString()
<< "airbaseName = \"" << airbaseName << "\", " << "airbaseName = \"" << airbaseName << "\", "
<< "country = \"" << country << "\", " << "country = \"" << country << "\", "
<< "units = " << "{" << unitsSS.str() << "}" << "}"; << "units = " << "{" << unitsSS.str() << "}" << "}";
commandSS << ", \"" << this->getHash() << "\"";
return commandSS.str(); return commandSS.str();
} }
@ -121,8 +131,11 @@ string SpawnHelicopters::getString()
<< "lat = " << spawnOptions[i].location.lat << ", " << "lat = " << spawnOptions[i].location.lat << ", "
<< "lng = " << spawnOptions[i].location.lng << ", " << "lng = " << spawnOptions[i].location.lng << ", "
<< "alt = " << spawnOptions[i].location.alt << ", " << "alt = " << spawnOptions[i].location.alt << ", "
<< "heading = " << spawnOptions[i].heading << ", "
<< "loadout = \"" << spawnOptions[i].loadout << "\"" << ", " << "loadout = \"" << spawnOptions[i].loadout << "\"" << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << " }, "; << "payload = " << spawnOptions[i].payload << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
} }
std::ostringstream commandSS; std::ostringstream commandSS;
@ -133,6 +146,7 @@ string SpawnHelicopters::getString()
<< "airbaseName = \"" << airbaseName << "\", " << "airbaseName = \"" << airbaseName << "\", "
<< "country = \"" << country << "\", " << "country = \"" << country << "\", "
<< "units = " << "{" << unitsSS.str() << "}" << "}"; << "units = " << "{" << unitsSS.str() << "}" << "}";
commandSS << ", \"" << this->getHash() << "\"";
return commandSS.str(); return commandSS.str();
} }
@ -248,4 +262,85 @@ string Explosion::getString()
<< location.lat << ", " << location.lat << ", "
<< location.lng; << location.lng;
return commandSS.str(); return commandSS.str();
}
/* FireLaser command */
string FireLaser::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.fireLaser, "
<< ID << ", "
<< code << ", "
<< destination.lat << ", "
<< destination.lng;
return commandSS.str();
}
/* FireInfrared command */
string FireInfrared::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.fireInfrared, "
<< ID << ", "
<< destination.lat << ", "
<< destination.lng;
return commandSS.str();
}
/* SetLaserCode command */
string SetLaserCode::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.setLaserCode, "
<< spotID << ", "
<< code;
return commandSS.str();
}
/* MoveSpot command */
string MoveSpot::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.moveSpot, "
<< spotID << ", "
<< destination.lat << ", "
<< destination.lng;
return commandSS.str();
}
/* DeleteSpot command */
string DeleteSpot::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.deleteSpot, "
<< spotID;
return commandSS.str();
}
/* SetCargoWeight command */
string SetCargoWeight::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.setCargoWeight, "
<< ID << ", "
<< weight;
return commandSS.str();
}
/* RegisterDrawArgument command */
string RegisterDrawArgument::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.registerDrawArgument, "
<< ID << ", "
<< argument << ", "
<< active;
return commandSS.str();
} }

View File

@ -22,6 +22,8 @@ Scheduler* scheduler = nullptr;
/* Data jsons */ /* Data jsons */
json::value missionData = json::value::object(); json::value missionData = json::value::object();
json::value drawingsByLayer = json::value::object();
json::value executionResults = json::value::object();
mutex mutexLock; mutex mutexLock;
string sessionHash; string sessionHash;
@ -161,3 +163,28 @@ extern "C" DllExport int coreMissionData(lua_State * L)
return(0); return(0);
} }
extern "C" DllExport int coreDrawingsData(lua_State* L)
{
log("Olympus coreDrawingsData called successfully");
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
lua_getglobal(L, "Olympus");
lua_getfield(L, -1, "drawingsByLayer");
luaTableToJSON(L, -1, drawingsByLayer);
return(0);
}
extern "C" DllExport int coreSetExecutionResults(lua_State* L)
{
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
lua_getglobal(L, "Olympus");
lua_getfield(L, -1, "executionResults");
luaTableToJSON(L, -1, executionResults, true);
return(0);
}

View File

@ -12,19 +12,24 @@ bool operator==(const DataTypes::Radio& lhs, const DataTypes::Radio& rhs)
bool operator==(const DataTypes::GeneralSettings& lhs, const DataTypes::GeneralSettings& rhs) bool operator==(const DataTypes::GeneralSettings& lhs, const DataTypes::GeneralSettings& rhs)
{ {
return lhs.prohibitAA == rhs.prohibitAA && lhs.prohibitAfterburner == rhs.prohibitAfterburner && lhs.prohibitAG == rhs.prohibitAG && return lhs.prohibitAA == rhs.prohibitAA && lhs.prohibitAfterburner == rhs.prohibitAfterburner && lhs.prohibitAG == rhs.prohibitAG &&
lhs.prohibitAirWpn == rhs.prohibitAirWpn && lhs.prohibitJettison == rhs.prohibitJettison; lhs.prohibitAirWpn == rhs.prohibitAirWpn && lhs.prohibitJettison == rhs.prohibitJettison;
} }
bool operator==(const DataTypes::Ammo& lhs, const DataTypes::Ammo& rhs) bool operator==(const DataTypes::Ammo& lhs, const DataTypes::Ammo& rhs)
{ {
return lhs.category == rhs.category && lhs.guidance == rhs.guidance && lhs.missileCategory == rhs.missileCategory && return lhs.category == rhs.category && lhs.guidance == rhs.guidance && lhs.missileCategory == rhs.missileCategory &&
lhs.quantity == rhs.quantity && strcmp(lhs.name, rhs.name) == 0; lhs.quantity == rhs.quantity && strcmp(lhs.name, rhs.name) == 0;
} }
bool operator==(const DataTypes::DrawArgument& lhs, const DataTypes::DrawArgument& rhs)
{
return lhs.argument == rhs.argument && lhs.value == rhs.value;
}
bool operator==(const DataTypes::Contact& lhs, const DataTypes::Contact& rhs) bool operator==(const DataTypes::Contact& lhs, const DataTypes::Contact& rhs)
{ {
return lhs.detectionMethod == rhs.detectionMethod && lhs.ID == rhs.ID; return lhs.detectionMethod == rhs.detectionMethod && lhs.ID == rhs.ID;
} }

View File

@ -0,0 +1,657 @@
#include "groundunit.h"
#include "utils.h"
#include "logger.h"
#include "commands.h"
#include "scheduler.h"
#include "defines.h"
#include "unitsmanager.h"
#include <GeographicLib/Geodesic.hpp>
using namespace GeographicLib;
extern Scheduler* scheduler;
extern UnitsManager* unitsManager;
json::value GroundUnit::database = json::value();
extern string instancePath;
#define RANDOM_ZERO_TO_ONE (double)(rand()) / (double)(RAND_MAX)
#define RANDOM_MINUS_ONE_TO_ONE (((double)(rand()) / (double)(RAND_MAX) - 0.5) * 2)
void GroundUnit::loadDatabase(string path) {
std::ifstream ifstream(instancePath + path);
std::stringstream ss;
ss << ifstream.rdbuf();
std::error_code errorCode;
database = json::value::parse(ss.str(), errorCode);
if (database.is_object())
log("GroundUnits database loaded correctly from " + instancePath + path);
else
log("Error reading GroundUnits database file");
}
/* Ground unit */
GroundUnit::GroundUnit(json::value json, unsigned int ID) : Unit(json, ID)
{
log("New Ground Unit created with ID: " + to_string(ID));
setCategory("GroundUnit");
setDesiredSpeed(10);
};
void GroundUnit::setDefaults(bool force)
{
/* Load gun values from database */
if (database.has_object_field(to_wstring(name))) {
json::value databaseEntry = database[to_wstring(name)];
if (databaseEntry.has_number_field(L"barrelHeight"))
setBarrelHeight(databaseEntry[L"barrelHeight"].as_number().to_double());
if (databaseEntry.has_number_field(L"muzzleVelocity"))
setMuzzleVelocity(databaseEntry[L"muzzleVelocity"].as_number().to_double());
if (databaseEntry.has_number_field(L"aimTime"))
setAimTime(databaseEntry[L"aimTime"].as_number().to_double());
if (databaseEntry.has_number_field(L"shotsToFire"))
setShotsToFire(databaseEntry[L"shotsToFire"].as_number().to_uint32());
if (databaseEntry.has_number_field(L"engagementRange"))
setEngagementRange(databaseEntry[L"engagementRange"].as_number().to_double());
if (databaseEntry.has_number_field(L"shotsBaseInterval"))
setShotsBaseInterval(databaseEntry[L"shotsBaseInterval"].as_number().to_double());
if (databaseEntry.has_number_field(L"shotsBaseScatter"))
setShotsBaseScatter(databaseEntry[L"shotsBaseScatter"].as_number().to_double());
if (databaseEntry.has_number_field(L"targetingRange"))
setTargetingRange(databaseEntry[L"targetingRange"].as_number().to_double());
if (databaseEntry.has_number_field(L"aimMethodRange"))
setAimMethodRange(databaseEntry[L"aimMethodRange"].as_number().to_double());
if (databaseEntry.has_number_field(L"acquisitionRange"))
setAcquisitionRange(databaseEntry[L"acquisitionRange"].as_number().to_double());
}
if (!getAlive() || !getControlled() || getHuman() || !getIsLeader()) return;
/* Set the default IDLE state */
setState(State::IDLE);
/* Set the default options */
setROE(ROE::OPEN_FIRE_WEAPON_FREE, force);
setOnOff(onOff, force);
setFollowRoads(followRoads, force);
}
void GroundUnit::setState(unsigned char newState)
{
Coords currentTargetPosition = getTargetPosition();
/************ Perform any action required when LEAVING a state ************/
if (newState != state) {
switch (state) {
case State::IDLE: {
break;
}
case State::REACH_DESTINATION: {
break;
}
case State::ATTACK: {
setTargetID(NULL);
break;
}
case State::FIRE_AT_AREA:
case State::SIMULATE_FIRE_FIGHT:
case State::SCENIC_AAA:
case State::MISS_ON_PURPOSE: {
setTargetPosition(Coords(NULL));
break;
}
default:
break;
}
}
/************ Perform any action required when ENTERING a state ************/
switch (newState) {
case State::IDLE: {
setTask("Idle");
setEnableTaskCheckFailed(false);
clearActivePath();
resetActiveDestination();
break;
}
case State::REACH_DESTINATION: {
setTask("Reaching destination");
setEnableTaskCheckFailed(true);
resetActiveDestination();
break;
}
case State::ATTACK: {
setEnableTaskCheckFailed(true);
clearActivePath();
resetActiveDestination();
break;
}
case State::FIRE_AT_AREA: {
setTask("Firing at area");
setTargetPosition(currentTargetPosition);
setEnableTaskCheckFailed(true);
clearActivePath();
resetActiveDestination();
break;
}
case State::SIMULATE_FIRE_FIGHT: {
setTask("Simulating fire fight");
setTargetPosition(currentTargetPosition);
setEnableTaskCheckFailed(false);
clearActivePath();
resetActiveDestination();
break;
}
case State::SCENIC_AAA: {
setTask("Scenic AAA");
setEnableTaskCheckFailed(false);
clearActivePath();
resetActiveDestination();
break;
}
case State::MISS_ON_PURPOSE: {
setTask("Miss on purpose");
setEnableTaskCheckFailed(false);
clearActivePath();
resetActiveDestination();
break;
}
default:
break;
}
setHasTask(false);
resetTaskFailedCounter();
nextTaskingMilliseconds = 0;
log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState));
state = newState;
triggerUpdate(DataIndex::state);
AIloop();
}
void GroundUnit::AIloop()
{
srand(static_cast<unsigned int>(time(NULL)) + ID);
unsigned long timeNow = std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1);
double currentAmmo = computeTotalAmmo();
/* Out of ammo */
if (shotsToFire > 0 && currentAmmo < shotsToFire && state != State::IDLE && state != State::REACH_DESTINATION)
setState(State::IDLE);
/* Account for unit reloading */
if (currentAmmo < oldAmmo)
totalShellsFired += oldAmmo - currentAmmo;
oldAmmo = currentAmmo;
switch (state) {
case State::IDLE: {
if (getHasTask())
resetTask();
break;
}
case State::REACH_DESTINATION: {
string enrouteTask = "";
bool looping = false;
std::ostringstream taskSS;
taskSS << "{ id = 'FollowRoads', value = " << (getFollowRoads() ? "true" : "false") << " }";
enrouteTask = taskSS.str();
if (activeDestination == NULL || !getHasTask())
{
if (!setActiveDestination())
setState(State::IDLE);
else
goToDestination(enrouteTask);
}
else {
if (isDestinationReached(GROUND_DEST_DIST_THR)) {
if (updateActivePath(looping) && setActiveDestination())
goToDestination(enrouteTask);
else
setState(State::IDLE);
}
}
break;
}
case State::ATTACK: {
Unit* target = unitsManager->getUnit(getTargetID());
if (target != nullptr) {
setTask("Attacking " + target->getUnitName());
if (!getHasTask()) {
/* Send the command */
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'AttackUnit', unitID = " << target->getID() << " }";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
}
else {
setState(State::IDLE);
}
break;
}
case State::FIRE_AT_AREA: {
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
if (targetPosition.alt == NULL) {
taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", radius = 100}";
}
else {
taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", alt = " << targetPosition.alt << ", radius = 100}";
}
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
break;
}
case State::SIMULATE_FIRE_FIGHT: {
string taskString = "";
if ((totalShellsFired - shellsFiredAtTasking >= shotsToFire || timeNow >= nextTaskingMilliseconds) && targetPosition != Coords(NULL)) {
if (scheduler->getLoad() > 100) {
taskString = "Excessive load, skipping tasking of unit";
setTargetPosition(Coords(NULL));
if (getHasTask())
resetTask();
}
else {
/* Get the distance and bearing to the target */
Coords scatteredTargetPosition = targetPosition;
double distance;
double bearing1;
double bearing2;
Geodesic::WGS84().Inverse(getPosition().lat, getPosition().lng, scatteredTargetPosition.lat, scatteredTargetPosition.lng, distance, bearing1, bearing2);
/* Apply a scatter to the aim */
bearing1 += RANDOM_MINUS_ONE_TO_ONE * (ShotsScatter::LOW - shotsScatter + 1) * 10;
/* Compute the scattered position applying a random scatter to the shot */
double scatterDistance = distance * tan(10 /* degs */ * (ShotsScatter::LOW - shotsScatter) / 57.29577 + 2 / 57.29577 /* degs */) * RANDOM_MINUS_ONE_TO_ONE;
Geodesic::WGS84().Direct(scatteredTargetPosition.lat, scatteredTargetPosition.lng, bearing1, scatterDistance, scatteredTargetPosition.lat, scatteredTargetPosition.lng);
/* Recover the data from the database */
bool indirectFire = false;
if (database.has_object_field(to_wstring(name))) {
json::value databaseEntry = database[to_wstring(name)];
if (databaseEntry.has_boolean_field(L"indirectFire"))
indirectFire = databaseEntry[L"indirectFire"].as_bool();
}
/* If the unit is of the indirect fire type, like a mortar, simply shoot at the target */
if (indirectFire) {
taskString += "Simulating fire fight with indirect fire";
log(unitName + "(" + name + ")" + " simulating fire fight with indirect fire");
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << scatteredTargetPosition.lat << ", lng = " << scatteredTargetPosition.lng << ", radius = 0.01}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
shellsFiredAtTasking = totalShellsFired;
setHasTask(true);
}
/* Otherwise use the aim method */
else {
taskString += "Simulating fire fight with aim point method. ";
log(unitName + "(" + name + ")" + " simulating fire fight with aim at point method");
string aimTaskString = aimAtPoint(scatteredTargetPosition);
taskString += aimTaskString;
}
/* Wait an amout of time depending on the shots intensity */
nextTaskingMilliseconds = timeNow + static_cast<unsigned long>(2 * aimTime * 1000);
}
}
if (targetPosition == Coords(NULL))
setState(State::IDLE);
/* Fallback if something went wrong */
if (timeNow >= nextTaskingMilliseconds)
nextTaskingMilliseconds = timeNow + static_cast<unsigned long>(3 * 1000);
setTimeToNextTasking(((nextTaskingMilliseconds - timeNow) / 1000.0));
if (taskString.length() > 0)
setTask(taskString);
break;
}
case State::SCENIC_AAA: {
string taskString = "";
/* Only perform scenic functions when the scheduler is "free" */
if (totalShellsFired - shellsFiredAtTasking >= shotsToFire || timeNow >= nextTaskingMilliseconds) {
if (scheduler->getLoad() > 100) {
taskString = "Excessive load, skipping tasking of unit";
setTargetPosition(Coords(NULL));
if (getHasTask())
resetTask();
}
else {
double distance = 0;
unsigned char unitCoalition = coalition == 0 ? getOperateAs() : coalition;
unsigned char targetCoalition = unitCoalition == 2 ? 1 : 2;
Unit* target = unitsManager->getClosestUnit(this, targetCoalition, { "Aircraft", "Helicopter" }, distance);
/* Recover the data from the database */
bool flak = false;
if (database.has_object_field(to_wstring(name))) {
json::value databaseEntry = database[to_wstring(name)];
if (databaseEntry.has_boolean_field(L"flak"))
flak = databaseEntry[L"flak"].as_bool();
}
/* Only run if an enemy air unit is closer than 20km to avoid useless load */
double activationDistance = 20000;
if (2 * engagementRange > activationDistance)
activationDistance = 2 * engagementRange;
if (target != nullptr && distance < activationDistance /* m */) {
double r = 15; /* m */
double barrelElevation = position.alt + barrelHeight + r * tan(acos(((double)(rand()) / (double)(RAND_MAX))));
double lat = 0;
double lng = 0;
double randomBearing = ((double)(rand()) / (double)(RAND_MAX)) * 360;
Geodesic::WGS84().Direct(position.lat, position.lng, randomBearing, r, lat, lng);
if (flak) {
lat = position.lat + RANDOM_MINUS_ONE_TO_ONE * (1 + (ShotsScatter::LOW - shotsScatter)) * 0.01;
lng = position.lng + RANDOM_MINUS_ONE_TO_ONE * (1 + (ShotsScatter::LOW - shotsScatter)) * 0.01;
barrelElevation = target->getPosition().alt + RANDOM_MINUS_ONE_TO_ONE * (ShotsScatter::LOW - shotsScatter) * 1000;
taskString += "Flak box mode";
}
else {
taskString += "Scenic AAA. Bearing: " + to_string((int)round(randomBearing)) + "deg";
}
taskString += ". Aim point elevation " + to_string((int)round(barrelElevation - position.alt)) + "m AGL";
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << lat << ", lng = " << lng << ", alt = " << barrelElevation << ", radius = 0.001 }";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
shellsFiredAtTasking = totalShellsFired;
setHasTask(true);
/* Wait an amout of time depending on the shots intensity */
nextTaskingMilliseconds = timeNow + static_cast<unsigned long>(2 * aimTime * 1000);
}
else {
setTargetPosition(Coords(NULL));
if (target == nullptr)
taskString += "Scenic AAA. No valid target.";
else
taskString += "Scenic AAA. Target outside max range: " + to_string((int)round(distance)) + "m.";
if (getHasTask())
resetTask();
}
}
}
if (timeNow >= nextTaskingMilliseconds)
nextTaskingMilliseconds = timeNow + static_cast<unsigned long>(3 * 1000);
setTimeToNextTasking((nextTaskingMilliseconds - timeNow) / 1000.0);
if (taskString.length() > 0)
setTask(taskString);
break;
}
case State::MISS_ON_PURPOSE: {
string taskString = "";
/* Check that the unit can perform AAA duties */
bool canAAA = false;
if (database.has_object_field(to_wstring(name))) {
json::value databaseEntry = database[to_wstring(name)];
if (databaseEntry.has_boolean_field(L"canAAA"))
canAAA = databaseEntry[L"canAAA"].as_bool();
}
/* Recover the data from the database */
bool flak = false;
if (database.has_object_field(to_wstring(name))) {
json::value databaseEntry = database[to_wstring(name)];
if (databaseEntry.has_boolean_field(L"flak"))
flak = databaseEntry[L"flak"].as_bool();
}
if (canAAA) {
/* Only perform scenic functions when the scheduler is "free" */
/* Only run this when the internal counter reaches 0 to avoid excessive computations when no nearby target */
if (totalShellsFired - shellsFiredAtTasking >= shotsToFire || timeNow >= nextTaskingMilliseconds) {
if (scheduler->getLoad() > 100) {
taskString = "Excessive load, skipping tasking of unit";
setTargetPosition(Coords(NULL));
if (getHasTask())
resetTask();
}
else {
double distance = 0;
unsigned char unitCoalition = coalition == 0 ? getOperateAs() : coalition;
unsigned char targetCoalition = unitCoalition == 2 ? 1 : 2;
/* Get all the units in range and select one at random */
double range = max(max(engagementRange, aimMethodRange), acquisitionRange);
map<Unit*, double> targets = unitsManager->getUnitsInRange(this, targetCoalition, { "Aircraft", "Helicopter" }, range);
Unit* target = nullptr;
unsigned int index = static_cast<unsigned int>((RANDOM_ZERO_TO_ONE * (targets.size() - 1)));
for (auto const& p : targets) {
if (index-- == 0) {
target = p.first;
distance = p.second;
}
}
/* Only do if we have a valid target close enough for AAA */
if (target != nullptr) {
taskString += "Missing on purpose. Valid target at range: " + to_string((int)round(distance)) + "m";
// Very simplified algorithm ignoring drag
double correctedAimTime = aimTime + distance / muzzleVelocity;
/* If the target is in targeting range and we are in highest precision mode, target it */
if (distance < targetingRange && shotsScatter == ShotsScatter::LOW) {
taskString += ". Range is less than targeting range (" + to_string((int)round(targetingRange)) + "m) and scatter is LOW, aiming at target.";
/* Send the command */
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'AttackUnit', unitID = " << target->getID() << " }";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
shellsFiredAtTasking = totalShellsFired;
setHasTask(true);
nextTaskingMilliseconds = timeNow + static_cast<unsigned long>(2 * aimTime * 1000);
}
/* Else, do miss on purpose */
else {
/* Compute where the target will be in aimTime seconds. */
double aimDistance = target->getHorizontalVelocity() * correctedAimTime;
double aimLat = 0;
double aimLng = 0;
Geodesic::WGS84().Direct(target->getPosition().lat, target->getPosition().lng, target->getTrack() * 57.29577, aimDistance, aimLat, aimLng); /* TODO make util to convert degrees and radians function */
double aimAlt = target->getPosition().alt + target->getVerticalVelocity();
if (flak) {
aimLat += RANDOM_MINUS_ONE_TO_ONE * (1 + (ShotsScatter::LOW - shotsScatter)) * 0.01;
aimLng += RANDOM_MINUS_ONE_TO_ONE * (1 + (ShotsScatter::LOW - shotsScatter)) * 0.01;
aimAlt += RANDOM_MINUS_ONE_TO_ONE * (1 + (ShotsScatter::LOW - shotsScatter)) * 1000;
}
/* Send the command */
if (distance < engagementRange) {
taskString += ". Range is less than engagement range (" + to_string((int)round(engagementRange)) + "m), using FIRE AT POINT method";
/* If the unit is closer than the engagement range, use the fire at point method */
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << aimLat << ", lng = " << aimLng << ", alt = " << aimAlt << ", radius = 0.001 }";
taskString += ". Aiming altitude " + to_string((int)round((aimAlt - position.alt) / 0.3048)) + "ft AGL";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
shellsFiredAtTasking = totalShellsFired;
setHasTask(true);
setTargetPosition(Coords(aimLat, aimLng, target->getPosition().alt));
nextTaskingMilliseconds = timeNow + static_cast<unsigned long>(2 * aimTime * 1000);
}
else if (distance < aimMethodRange) {
taskString += ". Range is less than aim method range (" + to_string((int)round(aimMethodRange / 0.3048)) + "ft), using AIM method.";
/* If the unit is closer than the aim method range, use the aim method range */
string aimMethodTask = aimAtPoint(Coords(aimLat, aimLng, aimAlt));
taskString += aimMethodTask;
setTargetPosition(Coords(aimLat, aimLng, target->getPosition().alt));
nextTaskingMilliseconds = timeNow + static_cast<unsigned long>(2 * aimTime * 1000);
}
else {
taskString += ". Target is not in range of weapon, waking up unit to get ready for tasking.";
/* Else just wake the unit up with an impossible command */
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << 0 << ", lng = " << 0 << ", alt = " << 0 << ", radius = 0.001, expendQty = " << 0 << " }";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
shellsFiredAtTasking = totalShellsFired;
setHasTask(true);
setTargetPosition(Coords(NULL));
/* Don't wait too long before checking again */
nextTaskingMilliseconds = timeNow + static_cast<unsigned long>(5 * 1000);
}
}
missOnPurposeTarget = target;
}
else {
taskString += "Missing on purpose. No target in range.";
setTargetPosition(Coords(NULL));
if (getHasTask())
resetTask();
}
}
}
/* If no valid target was detected */
if (timeNow >= nextTaskingMilliseconds) {
double alertnessTimeConstant = 10; /* s */
if (database.has_object_field(to_wstring(name))) {
json::value databaseEntry = database[to_wstring(name)];
if (databaseEntry.has_number_field(L"alertnessTimeConstant"))
alertnessTimeConstant = databaseEntry[L"alertnessTimeConstant"].as_number().to_double();
}
nextTaskingMilliseconds = timeNow + static_cast<unsigned long>((5 + RANDOM_ZERO_TO_ONE * alertnessTimeConstant) * 1000L);
missOnPurposeTarget = nullptr;
setTargetPosition(Coords(NULL));
}
}
else {
setState(State::IDLE);
}
setTimeToNextTasking((nextTaskingMilliseconds - timeNow) / 1000.0);
if (taskString.length() > 0)
setTask(taskString);
break;
}
default:
break;
}
}
string GroundUnit::aimAtPoint(Coords aimTarget) {
string taskString = "";
double dist;
double bearing1;
double bearing2;
Geodesic::WGS84().Inverse(position.lat, position.lng, aimTarget.lat, aimTarget.lng, dist, bearing1, bearing2);
/* Aim point distance */
double r = 15; /* m */
/* Compute the elevation angle of the gun*/
double deltaHeight = (aimTarget.alt - (position.alt + barrelHeight));
double alpha = 9.81 / 2 * dist * dist / (muzzleVelocity * muzzleVelocity);
double inner = dist * dist - 4 * alpha * (alpha + deltaHeight);
/* Check we can reach the target*/
if (inner > 0) {
/* Compute elevation and bearing */
double barrelElevation = r * (dist - sqrt(inner)) / (2 * alpha);
double lat = 0;
double lng = 0;
Geodesic::WGS84().Direct(position.lat, position.lng, bearing1, r, lat, lng);
taskString = +"Barrel elevation: " + to_string((int) round(barrelElevation)) + "m, bearing: " + to_string((int) round(bearing1)) + "deg";
log(unitName + "(" + name + ")" + " shooting with aim at point method. Barrel elevation: " + to_string(barrelElevation) + "m, bearing: " + to_string(bearing1) + "<EFBFBD>");
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << lat << ", lng = " << lng << ", alt = " << position.alt + barrelElevation + barrelHeight << ", radius = 0.001}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
shellsFiredAtTasking = totalShellsFired;
setHasTask(true);
}
else {
log("Target out of range for " + unitName + "(" + name + ")");
taskString = +"Target out of range";
}
return taskString;
}
void GroundUnit::changeSpeed(string change)
{
if (change.compare("stop") == 0)
setState(State::IDLE);
else if (change.compare("slow") == 0)
setDesiredSpeed(getDesiredSpeed() - knotsToMs(5));
else if (change.compare("fast") == 0)
setDesiredSpeed(getDesiredSpeed() + knotsToMs(5));
if (getDesiredSpeed() < 0)
setDesiredSpeed(0);
}
void GroundUnit::setOnOff(bool newOnOff, bool force)
{
if (newOnOff != onOff || force) {
Unit::setOnOff(newOnOff, force);
Command* command = dynamic_cast<Command*>(new SetOnOff(groupName, onOff));
scheduler->appendCommand(command);
}
}
void GroundUnit::setFollowRoads(bool newFollowRoads, bool force)
{
if (newFollowRoads != followRoads || force) {
Unit::setFollowRoads(newFollowRoads, force);
resetActiveDestination(); /* Reset active destination to apply option*/
}
}

View File

@ -37,13 +37,38 @@ NavyUnit::NavyUnit(json::value json, unsigned int ID) : Unit(json, ID)
void NavyUnit::setDefaults(bool force) void NavyUnit::setDefaults(bool force)
{ {
/* Load gun values from database */
if (database.has_object_field(to_wstring(name))) {
json::value databaseEntry = database[to_wstring(name)];
if (databaseEntry.has_number_field(L"barrelHeight"))
setBarrelHeight(databaseEntry[L"barrelHeight"].as_number().to_double());
if (databaseEntry.has_number_field(L"muzzleVelocity"))
setMuzzleVelocity(databaseEntry[L"muzzleVelocity"].as_number().to_double());
if (databaseEntry.has_number_field(L"aimTime"))
setAimTime(databaseEntry[L"aimTime"].as_number().to_double());
if (databaseEntry.has_number_field(L"shotsToFire"))
setShotsToFire(databaseEntry[L"shotsToFire"].as_number().to_uint32());
if (databaseEntry.has_number_field(L"engagementRange"))
setEngagementRange(databaseEntry[L"engagementRange"].as_number().to_double());
if (databaseEntry.has_number_field(L"shotsBaseInterval"))
setShotsBaseInterval(databaseEntry[L"shotsBaseInterval"].as_number().to_double());
if (databaseEntry.has_number_field(L"shotsBaseScatter"))
setShotsBaseScatter(databaseEntry[L"shotsBaseScatter"].as_number().to_double());
if (databaseEntry.has_number_field(L"targetingRange"))
setTargetingRange(databaseEntry[L"targetingRange"].as_number().to_double());
if (databaseEntry.has_number_field(L"aimMethodRange"))
setAimMethodRange(databaseEntry[L"aimMethodRange"].as_number().to_double());
if (databaseEntry.has_number_field(L"acquisitionRange"))
setAcquisitionRange(databaseEntry[L"acquisitionRange"].as_number().to_double());
}
if (!getAlive() || !getControlled() || getHuman() || !getIsLeader()) return; if (!getAlive() || !getControlled() || getHuman() || !getIsLeader()) return;
/* Set the default IDLE state */ /* Set the default IDLE state */
setState(State::IDLE); setState(State::IDLE);
/* Set the default options */ /* Set the default options */
setROE(ROE::WEAPON_FREE, force); setROE(ROE::OPEN_FIRE_WEAPON_FREE, force);
setOnOff(onOff, force); setOnOff(onOff, force);
setFollowRoads(followRoads, force); setFollowRoads(followRoads, force);
} }
@ -167,6 +192,7 @@ void NavyUnit::AIloop()
setState(State::IDLE); setState(State::IDLE);
} }
} }
break; break;
} }
case State::ATTACK: { case State::ATTACK: {
@ -187,6 +213,8 @@ void NavyUnit::AIloop()
else { else {
setState(State::IDLE); setState(State::IDLE);
} }
break;
} }
case State::FIRE_AT_AREA: { case State::FIRE_AT_AREA: {
setTask("Firing at area"); setTask("Firing at area");
@ -200,6 +228,8 @@ void NavyUnit::AIloop()
scheduler->appendCommand(command); scheduler->appendCommand(command);
setHasTask(true); setHasTask(true);
} }
break;
} }
case State::SIMULATE_FIRE_FIGHT: { case State::SIMULATE_FIRE_FIGHT: {
setTask("Simulating fire fight"); setTask("Simulating fire fight");
@ -207,6 +237,7 @@ void NavyUnit::AIloop()
// TODO // TODO
setState(State::IDLE); setState(State::IDLE);
break;
} }
default: default:
break; break;

View File

@ -52,10 +52,11 @@ void Scheduler::execute(lua_State* L)
if (command->getPriority() == priority) if (command->getPriority() == priority)
{ {
string commandString = "Olympus.protectedCall(" + command->getString() + ")"; string commandString = "Olympus.protectedCall(" + command->getString() + ")";
if (dostring_in(L, "server", (commandString))) string resultString = "";
if (dostring_in(L, "server", (commandString), resultString))
log("Error executing command " + commandString); log("Error executing command " + commandString);
else else
log("Command '" + commandString + "' executed correctly, current load " + to_string(getLoad())); log("Command '" + commandString + "' executed correctly, current load " + to_string(getLoad()) + ", result string: " + resultString);
/* Adjust the load depending on the fps */ /* Adjust the load depending on the fps */
double fpsMultiplier = 20; double fpsMultiplier = 20;
@ -64,7 +65,10 @@ void Scheduler::execute(lua_State* L)
load = static_cast<unsigned int>(command->getLoad() * fpsMultiplier); load = static_cast<unsigned int>(command->getLoad() * fpsMultiplier);
commands.remove(command); commands.remove(command);
executedCommandsHashes.push_back(command->getHash()); CommandResult commandResult = {
command->getHash(), resultString
};
executedCommandResults.push_back(commandResult);
command->executeCallback(); /* Execute the command callback (this is a lambda function that can be used to execute a function when the command is run) */ command->executeCallback(); /* Execute the command callback (this is a lambda function that can be used to execute a function when the command is run) */
delete command; delete command;
return; return;
@ -164,6 +168,12 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
string WP = to_string(i); string WP = to_string(i);
double lat = path[i][L"lat"].as_double(); double lat = path[i][L"lat"].as_double();
double lng = path[i][L"lng"].as_double(); double lng = path[i][L"lng"].as_double();
if (path[i].has_number_field(L"threshold")) {
double threshold = path[i][L"threshold"].as_double();
Coords dest; dest.lat = lat; dest.lng = lng; dest.threshold = threshold;
newPath.push_back(dest);
continue;
}
Coords dest; dest.lat = lat; dest.lng = lng; Coords dest; dest.lat = lat; dest.lng = lng;
newPath.push_back(dest); newPath.push_back(dest);
} }
@ -179,7 +189,7 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
string color = to_string(value[L"color"]); string color = to_string(value[L"color"]);
double lat = value[L"location"][L"lat"].as_double(); double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double(); double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng; Coords loc; loc.lat = lat; loc.lng = lng;
command = dynamic_cast<Command*>(new Smoke(color, loc)); command = dynamic_cast<Command*>(new Smoke(color, loc));
log(username + " added a " + color + " smoke at (" + to_string(lat) + ", " + to_string(lng) + ")", true); log(username + " added a " + color + " smoke at (" + to_string(lat) + ", " + to_string(lng) + ")", true);
@ -193,7 +203,10 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
string country = to_string(value[L"country"]); string country = to_string(value[L"country"]);
int spawnPoints = value[L"spawnPoints"].as_number().to_int32(); int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
if (!checkSpawnPoints(spawnPoints, coalition)) return; if (!checkSpawnPoints(spawnPoints, coalition)) {
log(username + " insufficient spawn points ", true);
return;
}
vector<SpawnOptions> spawnOptions; vector<SpawnOptions> spawnOptions;
for (auto unit : value[L"units"].as_array()) { for (auto unit : value[L"units"].as_array()) {
@ -201,11 +214,20 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
double lat = unit[L"location"][L"lat"].as_double(); double lat = unit[L"location"][L"lat"].as_double();
double lng = unit[L"location"][L"lng"].as_double(); double lng = unit[L"location"][L"lng"].as_double();
double alt = unit[L"altitude"].as_double(); double alt = unit[L"altitude"].as_double();
double heading = 0;
if (unit.has_number_field(L"heading"))
heading = unit[L"heading"].as_double();
Coords location; location.lat = lat; location.lng = lng; location.alt = alt; Coords location; location.lat = lat; location.lng = lng; location.alt = alt;
string loadout = to_string(unit[L"loadout"]); string loadout = to_string(unit[L"loadout"]);
string liveryID = to_string(unit[L"liveryID"]); string liveryID = to_string(unit[L"liveryID"]);
string skill = to_string(unit[L"skill"]);
spawnOptions.push_back({unitType, location, loadout, liveryID}); string payload = "nil";
if (unit.has_string_field(L"payload"))
payload = to_string(unit[L"payload"]);
spawnOptions.push_back({ unitType, location, loadout, skill, liveryID, heading, payload });
log(username + " spawned a " + coalition + " " + unitType, true); log(username + " spawned a " + coalition + " " + unitType, true);
} }
@ -222,17 +244,25 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
string country = to_string(value[L"country"]); string country = to_string(value[L"country"]);
int spawnPoints = value[L"spawnPoints"].as_number().to_int32(); int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
if (!checkSpawnPoints(spawnPoints, coalition)) return; if (!checkSpawnPoints(spawnPoints, coalition)) {
log(username + " insufficient spawn points ", true);
return;
}
vector<SpawnOptions> spawnOptions; vector<SpawnOptions> spawnOptions;
for (auto unit : value[L"units"].as_array()) { for (auto unit : value[L"units"].as_array()) {
string unitType = to_string(unit[L"unitType"]); string unitType = to_string(unit[L"unitType"]);
double lat = unit[L"location"][L"lat"].as_double(); double lat = unit[L"location"][L"lat"].as_double();
double lng = unit[L"location"][L"lng"].as_double(); double lng = unit[L"location"][L"lng"].as_double();
double heading = 0;
if (unit.has_number_field(L"heading"))
heading = unit[L"heading"].as_double();
Coords location; location.lat = lat; location.lng = lng; Coords location; location.lat = lat; location.lng = lng;
string liveryID = to_string(unit[L"liveryID"]); string liveryID = to_string(unit[L"liveryID"]);
string skill = to_string(unit[L"skill"]);
spawnOptions.push_back({ unitType, location, "", liveryID });
spawnOptions.push_back({ unitType, location, "", skill, liveryID, heading });
log(username + " spawned a " + coalition + " " + unitType, true); log(username + " spawned a " + coalition + " " + unitType, true);
} }
@ -342,18 +372,43 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
unit->setDesiredAltitudeType(to_string(value[L"altitudeType"])); unit->setDesiredAltitudeType(to_string(value[L"altitudeType"]));
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") altitude type: " + to_string(value[L"altitudeType"]), true); log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") altitude type: " + to_string(value[L"altitudeType"]), true);
} }
}/************************/
else if (key.compare("setRacetrack") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setRacetrackLength(value[L"length"].as_double());
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords location; location.lat = lat; location.lng = lng;
unit->setRacetrackAnchor(location);
unit->setRacetrackBearing(value[L"bearing"].as_double());
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") racetrack length: " + to_string(value[L"length"].as_double()) + " racetrack bearing: " + to_string(value[L"bearing"].as_double()), true);
}
} }
/************************/ /************************/
else if (key.compare("cloneUnits") == 0) else if (key.compare("cloneUnits") == 0)
{ {
vector<CloneOptions> cloneOptions; vector<CloneOptions> cloneOptions;
bool deleteOriginal = value[L"deleteOriginal"].as_bool(); bool deleteOriginal = value[L"deleteOriginal"].as_bool();
string coalition = to_string(value[L"coalition"]);
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
if (coalition.compare("all") != 0 && !checkSpawnPoints(spawnPoints, coalition)) {
log(username + " insufficient spawn points ", true);
return;
}
for (auto unit : value[L"units"].as_array()) { for (auto unit : value[L"units"].as_array()) {
unsigned int ID = unit[L"ID"].as_integer(); unsigned int ID = unit[L"ID"].as_integer();
double lat = unit[L"location"][L"lat"].as_double(); double lat = unit[L"location"][L"lat"].as_double();
double lng = unit[L"location"][L"lng"].as_double(); double lng = unit[L"location"][L"lng"].as_double();
Coords location; location.lat = lat; location.lng = lng; Coords location; location.lat = lat; location.lng = lng;
cloneOptions.push_back({ ID, location }); cloneOptions.push_back({ ID, location });
log(username + " cloning unit with ID " + to_string(ID), true); log(username + " cloning unit with ID " + to_string(ID), true);
@ -373,6 +428,20 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") ROE to " + to_string(ROE), true); log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") ROE to " + to_string(ROE), true);
} }
} }
else if (key.compare("setAlarmState") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unsigned char alarmState = value[L"alarmState"].as_number().to_uint32();
unit->setAlarmState(alarmState);
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") alarm state to " + to_string(alarmState), true);
}
else {
log("Error while setting setAlarmState. Unit does not exist.");
}
}
/************************/ /************************/
else if (key.compare("setReactionToThreat") == 0) else if (key.compare("setReactionToThreat") == 0)
{ {
@ -480,6 +549,29 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
} }
} }
/************************/ /************************/
else if (key.compare("setEngagementProperties") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
{
/* Engagement properties tasking */
unit->setBarrelHeight(value[L"barrelHeight"].as_number().to_double());
unit->setMuzzleVelocity(value[L"muzzleVelocity"].as_number().to_double());
unit->setAimTime(value[L"aimTime"].as_number().to_double());
unit->setShotsToFire(value[L"shotsToFire"].as_number().to_uint32());
unit->setShotsBaseInterval(value[L"shotsBaseInterval"].as_number().to_double());
unit->setShotsBaseScatter(value[L"shotsBaseScatter"].as_number().to_double());
unit->setEngagementRange(value[L"engagementRange"].as_number().to_double());
unit->setTargetingRange(value[L"targetingRange"].as_number().to_double());
unit->setAimMethodRange(value[L"aimMethodRange"].as_number().to_double());
unit->setAcquisitionRange(value[L"acquisitionRange"].as_number().to_double());
log(username + " updated unit " + unit->getUnitName() + "(" + unit->getName() + ") engagementProperties", true);
}
}
/************************/
else if (key.compare("setFollowRoads") == 0) else if (key.compare("setFollowRoads") == 0)
{ {
unsigned int ID = value[L"ID"].as_integer(); unsigned int ID = value[L"ID"].as_integer();
@ -500,7 +592,7 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
Unit* unit = unitsManager->getGroupLeader(ID); Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) { if (unit != nullptr) {
unit->setOnOff(onOff); unit->setOnOff(onOff);
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") onOff to: " + (onOff? "true": "false"), true); log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") onOff to: " + (onOff ? "true" : "false"), true);
} }
} }
/************************/ /************************/
@ -567,6 +659,11 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
double lat = value[L"location"][L"lat"].as_double(); double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double(); double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng; Coords loc; loc.lat = lat; loc.lng = lng;
if (value[L"location"].has_number_field(L"alt")) {
loc.alt = value[L"location"][L"alt"].as_double();
}
Unit* unit = unitsManager->getGroupLeader(ID); Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) { if (unit != nullptr) {
unit->setTargetPosition(loc); unit->setTargetPosition(loc);
@ -619,7 +716,7 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
unitsManager->acquireControl(ID); unitsManager->acquireControl(ID);
unsigned char operateAs = value[L"operateAs"].as_number().to_uint32(); unsigned char operateAs = value[L"operateAs"].as_number().to_uint32();
Unit* unit = unitsManager->getGroupLeader(ID); Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) if (unit != nullptr)
unit->setOperateAs(operateAs); unit->setOperateAs(operateAs);
} }
/************************/ /************************/
@ -666,7 +763,66 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
} }
} }
/************************/ /************************/
else if (key.compare("setCommandModeOptions") == 0) else if (key.compare("fireLaser") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr) {
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
unsigned int code = value[L"code"].as_integer();
log("Firing laser with code " + to_string(code) + " from unit " + unit->getUnitName() + " to (" + to_string(lat) + ", " + to_string(lng) + ")");
command = dynamic_cast<Command*>(new FireLaser(ID, code, loc));
}
}
/************************/
else if (key.compare("fireInfrared") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr) {
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
log("Firing infrared from unit " + unit->getUnitName() + " to (" + to_string(lat) + ", " + to_string(lng) + ")");
command = dynamic_cast<Command*>(new FireInfrared(ID, loc));
}
}
/************************/
else if (key.compare("setLaserCode") == 0)
{
unsigned int spotID = value[L"spotID"].as_integer();
unsigned int code = value[L"code"].as_integer();
log("Setting laser code " + to_string(code) + " to spot with ID " + to_string(spotID));
command = dynamic_cast<Command*>(new SetLaserCode(spotID, code));
}
/************************/
else if (key.compare("moveSpot") == 0)
{
unsigned int spotID = value[L"spotID"].as_integer();
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
log("Moving spot with ID " + to_string(spotID) + " to (" + to_string(lat) + ", " + to_string(lng) + ")");
command = dynamic_cast<Command*>(new MoveSpot(spotID, loc));
}
/************************/
else if (key.compare("deleteSpot") == 0)
{
unsigned int spotID = value[L"spotID"].as_integer();
log("Deleting spot with ID " + to_string(spotID));
command = dynamic_cast<Command*>(new DeleteSpot(spotID));
}
/************************/
else if (key.compare("setCommandModeOptions") == 0)
{ {
setCommandModeOptions(value); setCommandModeOptions(value);
log(username + " updated the Command Mode Options", true); log(username + " updated the Command Mode Options", true);
@ -676,6 +832,53 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
unitsManager->loadDatabases(); unitsManager->loadDatabases();
} }
/************************/ /************************/
else if (key.compare("setCargoWeight") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr) {
double weight = value[L"weight"].as_double();
unit->setCargoWeight(weight);
log(username + " set weight to unit " + unit->getUnitName() + "(" + unit->getName() + "), " + to_string(weight), true);
}
}
/************************/
else if (key.compare("registerDrawArgument") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr) {
int argument = value[L"argument"].as_integer();
bool active = value[L"active"].as_bool();
command = dynamic_cast<Command*>(new RegisterDrawArgument(ID, argument, active));
log(username + " registered draw argument " + to_string(argument) + " for unit " + unit->getUnitName() + "(" + unit->getName() + "), value:" + to_string(active), true);
}
}
/************************/
else if (key.compare("setCustomString") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr) {
string customString = to_string(value[L"customString"]);
unit->setCustomString(customString);
log(username + " set custom string to unit " + unit->getUnitName() + "(" + unit->getName() + "), " + customString, true);
}
}
/************************/
else if (key.compare("setCustomInteger") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr) {
double customNumber = value[L"customInteger"].as_double();
unit->setCustomInteger(customNumber);
log(username + " set custom number to unit " + unit->getUnitName() + "(" + unit->getName() + "), " + to_string(customNumber), true);
}
}
/************************/
else else
{ {
log("Unknown command: " + key); log("Unknown command: " + key);

View File

@ -2,6 +2,7 @@
#include "logger.h" #include "logger.h"
#include "luatools.h" #include "luatools.h"
#include "dcstools.h" #include "dcstools.h"
#include "defines.h"
#include <algorithm> #include <algorithm>
@ -38,9 +39,9 @@ void registerLuaFunctions(lua_State* L)
log("protectedCall registered successfully"); log("protectedCall registered successfully");
} }
executeLuaScript(L, instancePath + "..\\Scripts\\mist.lua"); executeLuaScript(L, instancePath + MIST_SCRIPT);
executeLuaScript(L, instancePath + "..\\Scripts\\OlympusCommand.lua"); executeLuaScript(L, instancePath + OLYMPUS_COMMAND_SCRIPT);
executeLuaScript(L, instancePath + "..\\Scripts\\unitPayloads.lua"); executeLuaScript(L, instancePath + UNIT_PAYLOADS_SCRIPT);
executeLuaScript(L, instancePath + "..\\Scripts\\templates.lua"); executeLuaScript(L, instancePath + TEMPLATES_SCRIPT);
executeLuaScript(L, instancePath + "..\\Scripts\\mods.lua"); executeLuaScript(L, instancePath + MODS_SCRIPT);
} }

View File

@ -17,6 +17,8 @@ extern UnitsManager* unitsManager;
extern WeaponsManager* weaponsManager; extern WeaponsManager* weaponsManager;
extern Scheduler* scheduler; extern Scheduler* scheduler;
extern json::value missionData; extern json::value missionData;
extern json::value drawingsByLayer;
extern json::value executionResults;
extern mutex mutexLock; extern mutex mutexLock;
extern string sessionHash; extern string sessionHash;
extern string instancePath; extern string instancePath;
@ -128,6 +130,9 @@ void Server::handle_get(http_request request)
/* Bullseyes data */ /* Bullseyes data */
else if (URI.compare(BULLSEYE_URI) == 0 && missionData.has_object_field(L"bullseyes")) else if (URI.compare(BULLSEYE_URI) == 0 && missionData.has_object_field(L"bullseyes"))
answer[L"bullseyes"] = missionData[L"bullseyes"]; answer[L"bullseyes"] = missionData[L"bullseyes"];
/* Spots (laser/IR) data */
else if (URI.compare(SPOTS_URI) == 0 && missionData.has_object_field(L"spots"))
answer[L"spots"] = missionData[L"spots"];
/* Mission data */ /* Mission data */
else if (URI.compare(MISSION_URI) == 0 && missionData.has_object_field(L"mission")) { else if (URI.compare(MISSION_URI) == 0 && missionData.has_object_field(L"mission")) {
answer[L"mission"] = missionData[L"mission"]; answer[L"mission"] = missionData[L"mission"];
@ -145,6 +150,14 @@ void Server::handle_get(http_request request)
} }
else if (URI.compare(COMMANDS_URI) == 0 && query.find(L"commandHash") != query.end()) { else if (URI.compare(COMMANDS_URI) == 0 && query.find(L"commandHash") != query.end()) {
answer[L"commandExecuted"] = json::value(scheduler->isCommandExecuted(to_string(query[L"commandHash"]))); answer[L"commandExecuted"] = json::value(scheduler->isCommandExecuted(to_string(query[L"commandHash"])));
if (executionResults.has_field(query[L"commandHash"]))
answer[L"commandResult"] = executionResults[query[L"commandHash"]];
else
answer[L"commandResult"] = json::value::null();
}
/* Drawings data*/
else if (URI.compare(DRAWINGS_URI) == 0 && drawingsByLayer.has_object_field(L"drawings")) {
answer[L"drawings"] = drawingsByLayer[L"drawings"];
} }
/* Common data */ /* Common data */
@ -296,14 +309,14 @@ void Server::task()
ss << ifstream.rdbuf(); ss << ifstream.rdbuf();
std::error_code errorCode; std::error_code errorCode;
json::value config = json::value::parse(ss.str(), errorCode); json::value config = json::value::parse(ss.str(), errorCode);
if (config.is_object() && config.has_object_field(L"server") && if (config.is_object() && config.has_object_field(L"backend") &&
config[L"server"].has_string_field(L"address") && config[L"server"].has_number_field(L"port")) config[L"backend"].has_string_field(L"address") && config[L"backend"].has_number_field(L"port"))
{ {
address = "http://" + to_string(config[L"server"][L"address"]) + ":" + to_string(config[L"server"][L"port"].as_number().to_int32()); address = "http://" + to_string(config[L"backend"][L"address"]) + ":" + to_string(config[L"backend"][L"port"].as_number().to_int32());
log("Starting server on " + address); log("Starting backend on " + address);
} }
else else
log("Error reading configuration file. Starting server on " + address); log("Error reading configuration file. Starting backend on " + address);
if (config.is_object() && config.has_object_field(L"authentication")) if (config.is_object() && config.has_object_field(L"authentication"))
{ {

View File

@ -28,25 +28,6 @@ Unit::~Unit()
void Unit::initialize(json::value json) void Unit::initialize(json::value json)
{ {
if (json.has_string_field(L"name"))
setName(to_string(json[L"name"]));
if (json.has_string_field(L"unitName"))
setUnitName(to_string(json[L"unitName"]));
if (json.has_string_field(L"groupName"))
setGroupName(to_string(json[L"groupName"]));
if (json.has_number_field(L"coalitionID"))
setCoalition(json[L"coalitionID"].as_number().to_int32());
//if (json.has_number_field(L"Country"))
// setCountry(json[L"Country"].as_number().to_int32());
/* All units which contain the name "Olympus" are automatically under AI control */
if (getUnitName().find("Olympus") != string::npos)
setControlled(true);
update(json, 0); update(json, 0);
setDefaults(); setDefaults();
} }
@ -54,6 +35,32 @@ void Unit::initialize(json::value json)
void Unit::update(json::value json, double dt) void Unit::update(json::value json, double dt)
{ {
if (json.has_string_field(L"name"))
setName(to_string(json[L"name"]));
if (json.has_string_field(L"unitName"))
setUnitName(to_string(json[L"unitName"]));
if (json.has_number_field(L"groupID"))
setGroupID(json[L"groupID"].as_number().to_uint32());
if (json.has_number_field(L"unitID"))
setUnitID(json[L"unitID"].as_number().to_uint32());
if (json.has_string_field(L"groupName"))
setGroupName(to_string(json[L"groupName"]));
if (json.has_string_field(L"callsign"))
setCallsign(to_string(json[L"callsign"]));
if (json.has_number_field(L"coalitionID"))
setCoalition(json[L"coalitionID"].as_number().to_int32());
if (json.has_number_field(L"country"))
setCountry(json[L"country"].as_number().to_int32());
/* All units which contain the name "Olympus" are automatically under AI control */
if (getUnitName().find("Olympus") != string::npos)
setControlled(true);
if (json.has_object_field(L"position")) if (json.has_object_field(L"position"))
{ {
setPosition({ setPosition({
@ -81,6 +88,9 @@ void Unit::update(json::value json, double dt)
if (json.has_boolean_field(L"isAlive")) if (json.has_boolean_field(L"isAlive"))
setAlive(json[L"isAlive"].as_bool()); setAlive(json[L"isAlive"].as_bool());
if (json.has_boolean_field(L"radarState"))
setRadarState(json[L"radarState"].as_bool());
if (json.has_boolean_field(L"isHuman")) if (json.has_boolean_field(L"isHuman"))
setHuman(json[L"isHuman"].as_bool()); setHuman(json[L"isHuman"].as_bool());
@ -118,6 +128,20 @@ void Unit::update(json::value json, double dt)
setAmmo(ammo); setAmmo(ammo);
} }
if (json.has_object_field(L"drawArguments")) {
vector<DataTypes::DrawArgument> drawArguments;
for (auto const& el : json[L"drawArguments"].as_object()) {
DataTypes::DrawArgument drawArgumentItem;
auto drawArgumentJson = el.second;
if (drawArgumentJson.has_number_field(L"argument"))
drawArgumentItem.argument = drawArgumentJson[L"argument"].as_number().to_uint32();
if (drawArgumentJson.has_number_field(L"value"))
drawArgumentItem.value = drawArgumentJson[L"value"].as_number().to_double();
drawArguments.push_back(drawArgumentItem);
}
setDrawArguments(drawArguments);
}
if (json.has_object_field(L"contacts")) { if (json.has_object_field(L"contacts")) {
vector<DataTypes::Contact> contacts; vector<DataTypes::Contact> contacts;
for (auto const& el : json[L"contacts"].as_object()) { for (auto const& el : json[L"contacts"].as_object()) {
@ -143,12 +167,15 @@ void Unit::update(json::value json, double dt)
if (json.has_number_field(L"health")) if (json.has_number_field(L"health"))
setHealth(static_cast<unsigned char>(json[L"health"].as_number().to_uint32())); setHealth(static_cast<unsigned char>(json[L"health"].as_number().to_uint32()));
if (json.has_boolean_field(L"airborne"))
setAirborne(json[L"airborne"].as_bool());
runAILoop(); runAILoop();
} }
void Unit::setDefaults(bool force) void Unit::setDefaults(bool force)
{ {
setAlarmState(AlarmState::AUTO, force);
} }
void Unit::runAILoop() { void Unit::runAILoop() {
@ -206,6 +233,7 @@ void Unit::refreshLeaderData(unsigned long long time) {
case DataIndex::operateAs: updateValue(operateAs, leader->operateAs, datumIndex); break; case DataIndex::operateAs: updateValue(operateAs, leader->operateAs, datumIndex); break;
case DataIndex::shotsScatter: updateValue(shotsScatter, leader->shotsScatter, datumIndex); break; case DataIndex::shotsScatter: updateValue(shotsScatter, leader->shotsScatter, datumIndex); break;
case DataIndex::shotsIntensity: updateValue(shotsIntensity, leader->shotsIntensity, datumIndex); break; case DataIndex::shotsIntensity: updateValue(shotsIntensity, leader->shotsIntensity, datumIndex); break;
case DataIndex::alarmState: updateValue(alarmState, leader->alarmState, datumIndex); break;
} }
} }
} }
@ -241,6 +269,10 @@ void Unit::getData(stringstream& ss, unsigned long long time)
appendString(ss, datumIndex, category); appendString(ss, datumIndex, category);
datumIndex = DataIndex::alive; datumIndex = DataIndex::alive;
appendNumeric(ss, datumIndex, alive); appendNumeric(ss, datumIndex, alive);
datumIndex = DataIndex::unitID;
appendNumeric(ss, datumIndex, unitID);
datumIndex = DataIndex::groupID;
appendNumeric(ss, datumIndex, groupID);
} }
else { else {
for (unsigned char datumIndex = DataIndex::startOfData + 1; datumIndex < DataIndex::lastIndex; datumIndex++) for (unsigned char datumIndex = DataIndex::startOfData + 1; datumIndex < DataIndex::lastIndex; datumIndex++)
@ -249,12 +281,17 @@ void Unit::getData(stringstream& ss, unsigned long long time)
switch (datumIndex) { switch (datumIndex) {
case DataIndex::category: appendString(ss, datumIndex, category); break; case DataIndex::category: appendString(ss, datumIndex, category); break;
case DataIndex::alive: appendNumeric(ss, datumIndex, alive); break; case DataIndex::alive: appendNumeric(ss, datumIndex, alive); break;
case DataIndex::alarmState: appendNumeric(ss, datumIndex, alarmState); break;
case DataIndex::radarState: appendNumeric(ss, datumIndex, radarState); break;
case DataIndex::human: appendNumeric(ss, datumIndex, human); break; case DataIndex::human: appendNumeric(ss, datumIndex, human); break;
case DataIndex::controlled: appendNumeric(ss, datumIndex, controlled); break; case DataIndex::controlled: appendNumeric(ss, datumIndex, controlled); break;
case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break; case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break;
case DataIndex::country: appendNumeric(ss, datumIndex, country); break; case DataIndex::country: appendNumeric(ss, datumIndex, country); break;
case DataIndex::name: appendString(ss, datumIndex, name); break; case DataIndex::name: appendString(ss, datumIndex, name); break;
case DataIndex::unitName: appendString(ss, datumIndex, unitName); break; case DataIndex::unitName: appendString(ss, datumIndex, unitName); break;
case DataIndex::callsign: appendString(ss, datumIndex, callsign); break;
case DataIndex::unitID: appendNumeric(ss, datumIndex, unitID); break;
case DataIndex::groupID: appendNumeric(ss, datumIndex, groupID); break;
case DataIndex::groupName: appendString(ss, datumIndex, groupName); break; case DataIndex::groupName: appendString(ss, datumIndex, groupName); break;
case DataIndex::state: appendNumeric(ss, datumIndex, state); break; case DataIndex::state: appendNumeric(ss, datumIndex, state); break;
case DataIndex::task: appendString(ss, datumIndex, task); break; case DataIndex::task: appendString(ss, datumIndex, task); break;
@ -292,6 +329,25 @@ void Unit::getData(stringstream& ss, unsigned long long time)
case DataIndex::shotsScatter: appendNumeric(ss, datumIndex, shotsScatter); break; case DataIndex::shotsScatter: appendNumeric(ss, datumIndex, shotsScatter); break;
case DataIndex::shotsIntensity: appendNumeric(ss, datumIndex, shotsIntensity); break; case DataIndex::shotsIntensity: appendNumeric(ss, datumIndex, shotsIntensity); break;
case DataIndex::health: appendNumeric(ss, datumIndex, health); break; case DataIndex::health: appendNumeric(ss, datumIndex, health); break;
case DataIndex::racetrackLength: appendNumeric(ss, datumIndex, racetrackLength); break;
case DataIndex::racetrackAnchor: appendNumeric(ss, datumIndex, racetrackAnchor); break;
case DataIndex::racetrackBearing: appendNumeric(ss, datumIndex, racetrackBearing); break;
//case DataIndex::timeToNextTasking: appendNumeric(ss, datumIndex, timeToNextTasking); break; Useful for debugging, but useless in production and very data hungry
case DataIndex::barrelHeight: appendNumeric(ss, datumIndex, barrelHeight); break;
case DataIndex::muzzleVelocity: appendNumeric(ss, datumIndex, muzzleVelocity); break;
case DataIndex::aimTime: appendNumeric(ss, datumIndex, aimTime); break;
case DataIndex::shotsToFire: appendNumeric(ss, datumIndex, shotsToFire); break;
case DataIndex::shotsBaseInterval: appendNumeric(ss, datumIndex, shotsBaseInterval); break;
case DataIndex::shotsBaseScatter: appendNumeric(ss, datumIndex, shotsBaseScatter); break;
case DataIndex::engagementRange: appendNumeric(ss, datumIndex, engagementRange); break;
case DataIndex::targetingRange: appendNumeric(ss, datumIndex, targetingRange); break;
case DataIndex::aimMethodRange: appendNumeric(ss, datumIndex, aimMethodRange); break;
case DataIndex::acquisitionRange: appendNumeric(ss, datumIndex, acquisitionRange); break;
case DataIndex::airborne: appendNumeric(ss, datumIndex, airborne); break;
case DataIndex::cargoWeight: appendNumeric(ss, datumIndex, cargoWeight); break;
case DataIndex::drawArguments: appendVector(ss, datumIndex, drawArguments); break;
case DataIndex::customString: appendString(ss, datumIndex, customString); break;
case DataIndex::customInteger: appendNumeric(ss, datumIndex, customInteger); break;
} }
} }
} }
@ -450,6 +506,17 @@ void Unit::setROE(unsigned char newROE, bool force)
} }
} }
void Unit::setAlarmState(unsigned char newAlarmState, bool force)
{
if (alarmState != newAlarmState || force) {
alarmState = newAlarmState;
Command* command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ALARM_STATE, static_cast<unsigned int>(newAlarmState)));
scheduler->appendCommand(command);
triggerUpdate(DataIndex::alarmState);
}
}
void Unit::setReactionToThreat(unsigned char newReactionToThreat, bool force) void Unit::setReactionToThreat(unsigned char newReactionToThreat, bool force)
{ {
if (reactionToThreat != newReactionToThreat || force) { if (reactionToThreat != newReactionToThreat || force) {
@ -652,6 +719,24 @@ void Unit::setGeneralSettings(DataTypes::GeneralSettings newGeneralSettings, boo
} }
} }
void Unit::setDrawArguments(vector<DataTypes::DrawArgument> newDrawArguments)
{
if (drawArguments.size() == newDrawArguments.size()) {
bool equal = true;
for (int i = 0; i < drawArguments.size(); i++) {
if (drawArguments.at(i) != newDrawArguments.at(i))
{
equal = false;
break;
}
}
if (equal)
return;
}
drawArguments = newDrawArguments;
triggerUpdate(DataIndex::drawArguments);
}
void Unit::setDesiredSpeed(double newDesiredSpeed) void Unit::setDesiredSpeed(double newDesiredSpeed)
{ {
if (desiredSpeed != newDesiredSpeed) { if (desiredSpeed != newDesiredSpeed) {
@ -718,6 +803,7 @@ void Unit::goToDestination(string enrouteTask)
} }
} }
// NOTE: if the current active path has a threshold set, that value will be used instead of the passed one
bool Unit::isDestinationReached(double threshold) bool Unit::isDestinationReached(double threshold)
{ {
if (activeDestination != NULL) if (activeDestination != NULL)
@ -727,7 +813,7 @@ bool Unit::isDestinationReached(double threshold)
{ {
double dist = 0; double dist = 0;
Geodesic::WGS84().Inverse(p->getPosition().lat, p->getPosition().lng, activeDestination.lat, activeDestination.lng, dist); Geodesic::WGS84().Inverse(p->getPosition().lat, p->getPosition().lng, activeDestination.lat, activeDestination.lng, dist);
if (dist < threshold) if (dist < (activeDestination.threshold == 0? threshold: activeDestination.threshold))
{ {
log(unitName + " destination reached"); log(unitName + " destination reached");
return true; return true;
@ -808,3 +894,11 @@ void Unit::setHasTaskAssigned(bool newHasTaskAssigned) {
void Unit::triggerUpdate(unsigned char datumIndex) { void Unit::triggerUpdate(unsigned char datumIndex) {
updateTimeMap[datumIndex] = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); updateTimeMap[datumIndex] = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
} }
unsigned int Unit::computeTotalAmmo()
{
unsigned int totalShells = 0;
for (auto const& ammoItem : ammo)
totalShells += ammoItem.quantity;
return totalShells;
}

View File

@ -151,7 +151,7 @@ void UnitsManager::deleteUnit(unsigned int ID, bool explosion, string explosionT
} }
} }
Unit* UnitsManager::getClosestUnit(Unit* unit, unsigned char coalition, vector<string> categories, double &distance) { Unit* UnitsManager::getClosestUnit(Unit* unit, unsigned char coalition, vector<string> categories, double &distance, bool airborneOnly) {
Unit* closestUnit = nullptr; Unit* closestUnit = nullptr;
distance = 0; distance = 0;
@ -167,6 +167,9 @@ Unit* UnitsManager::getClosestUnit(Unit* unit, unsigned char coalition, vector<s
/* Check if the unit belongs to the desired coalition, is alive, and is of the category requested */ /* Check if the unit belongs to the desired coalition, is alive, and is of the category requested */
if (requestedCategory && p.second->getCoalition() == coalition && p.second->getAlive()) { if (requestedCategory && p.second->getCoalition() == coalition && p.second->getAlive()) {
/* Check if the unit is airborne */
if (airborneOnly && !p.second->getAirborne())
continue;
/* Compute the distance from the unit to the tested unit */ /* Compute the distance from the unit to the tested unit */
double dist; double dist;
double bearing1; double bearing1;
@ -194,10 +197,13 @@ Unit* UnitsManager::getClosestUnit(Unit* unit, unsigned char coalition, vector<s
return closestUnit; return closestUnit;
} }
map<Unit*, double> UnitsManager::getUnitsInRange(Unit* unit, unsigned char coalition, vector<string> categories, double range) { map<Unit*, double> UnitsManager::getUnitsInRange(Unit* unit, unsigned char coalition, vector<string> categories, double range, bool airborneOnly) {
map<Unit*, double> unitsInRange; map<Unit*, double> unitsInRange;
for (auto const& p : units) { for (auto const& p : units) {
if (airborneOnly && !p.second->getAirborne())
continue;
/* Check if the units category is of the correct type */ /* Check if the units category is of the correct type */
bool requestedCategory = false; bool requestedCategory = false;
for (auto const& category : categories) { for (auto const& category : categories) {

View File

@ -113,4 +113,11 @@ Bomb::Bomb(json::value json, unsigned int ID) : Weapon(json, ID)
{ {
log("New Bomb created with ID: " + to_string(ID)); log("New Bomb created with ID: " + to_string(ID));
setCategory("Bomb"); setCategory("Bomb");
};
/* Shell */
Shell::Shell(json::value json, unsigned int ID) : Weapon(json, ID)
{
log("New Shell created with ID: " + to_string(ID));
setCategory("Shell");
}; };

View File

@ -41,6 +41,8 @@ void WeaponsManager::update(json::value& json, double dt)
weapons[ID] = dynamic_cast<Weapon*>(new Missile(p.second, ID)); weapons[ID] = dynamic_cast<Weapon*>(new Missile(p.second, ID));
else if (category.compare("Bomb") == 0) else if (category.compare("Bomb") == 0)
weapons[ID] = dynamic_cast<Weapon*>(new Bomb(p.second, ID)); weapons[ID] = dynamic_cast<Weapon*>(new Bomb(p.second, ID));
else if (category.compare("Shell") == 0)
weapons[ID] = dynamic_cast<Weapon*>(new Shell(p.second, ID));
/* Initialize the weapon if creation was successfull */ /* Initialize the weapon if creation was successfull */
if (weapons.count(ID) != 0) { if (weapons.count(ID) != 0) {

View File

@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 FILEVERSION 2,0,0,0
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -79,12 +79,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "DCS Olympus" VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus" VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "dcstools.dll" VALUE "InternalName", "dcstools.dll"
VALUE "LegalCopyright", "Copyright (C) 2023" VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "dcstools.dll" VALUE "OriginalFilename", "dcstools.dll"
VALUE "ProductName", "DCS Olympus" VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "ProductVersion", "2.0.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -77,23 +77,23 @@
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir> <OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>

View File

@ -7,6 +7,7 @@ void DllExport LogWarning(lua_State* L, string message);
void DllExport LogError(lua_State* L, string message); void DllExport LogError(lua_State* L, string message);
void DllExport Log(lua_State* L, string message, unsigned int level); void DllExport Log(lua_State* L, string message, unsigned int level);
int DllExport dostring_in(lua_State* L, string target, string command); int DllExport dostring_in(lua_State* L, string target, string command);
int DllExport dostring_in(lua_State* L, string target, string command, string& result);
void DllExport getAllUnits(lua_State* L, map<unsigned int, json::value>& unitJSONs); void DllExport getAllUnits(lua_State* L, map<unsigned int, json::value>& unitJSONs);
unsigned int DllExport TACANChannelToFrequency(unsigned int channel, char XY); unsigned int DllExport TACANChannelToFrequency(unsigned int channel, char XY);

View File

@ -101,7 +101,24 @@ int dostring_in(lua_State* L, string target, string command)
lua_getfield(L, -1, "dostring_in"); lua_getfield(L, -1, "dostring_in");
lua_pushstring(L, target.c_str()); lua_pushstring(L, target.c_str());
lua_pushstring(L, command.c_str()); lua_pushstring(L, command.c_str());
return lua_pcall(L, 2, 0, 0); int res = lua_pcall(L, 2, 0, 0);
return res;
}
int dostring_in(lua_State* L, string target, string command, string &result)
{
lua_getglobal(L, "net");
lua_getfield(L, -1, "dostring_in");
lua_pushstring(L, target.c_str());
lua_pushstring(L, command.c_str());
int res = lua_pcall(L, 2, 0, 0);
// Get the first result in the stack
if (lua_isstring(L, -1)) {
result = lua_tostring(L, -1);
}
return res;
} }
unsigned int TACANChannelToFrequency(unsigned int channel, char XY) unsigned int TACANChannelToFrequency(unsigned int channel, char XY)

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "framework.h" #include "framework.h"
void DllExport setLogDirectory(std::string m_dirPath);
void DllExport log(const std::string& sMessage, bool addToJSON = false); void DllExport log(const std::string& sMessage, bool addToJSON = false);
void DllExport log(const std::wstring& sMessage, bool addToJSON = false); void DllExport log(const std::wstring& sMessage, bool addToJSON = false);
void DllExport getLogsJSON(json::value& json, unsigned long long time); void DllExport getLogsJSON(json::value& json, unsigned long long time);

View File

@ -8,6 +8,7 @@ public:
void log(const string& sMessage, bool addToJSON); void log(const string& sMessage, bool addToJSON);
void log(const wstring& sMessage, bool addToJSON); void log(const wstring& sMessage, bool addToJSON);
void toJSON(json::value& json, unsigned long long time); void toJSON(json::value& json, unsigned long long time);
void setDirectory(string newDirPath);
static Logger* GetLogger(); static Logger* GetLogger();
@ -20,9 +21,11 @@ private:
static Logger* m_pThis; static Logger* m_pThis;
static ofstream m_Logfile; static ofstream m_Logfile;
static std::map<unsigned long long, std::string> m_logs; static std::map<unsigned long long, std::string> m_logs;
static string m_dirPath;
mutex mutexLock; mutex mutexLock;
void Clear();
void Open(); void Open();
void Close(); void Close();
}; };

View File

@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 FILEVERSION 2,0,0,0
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -79,12 +79,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "DCS Olympus" VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus" VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "logger.dll" VALUE "InternalName", "logger.dll"
VALUE "LegalCopyright", "Copyright (C) 2023" VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "logger.dll" VALUE "OriginalFilename", "logger.dll"
VALUE "ProductName", "DCS Olympus" VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "ProductVersion", "2.0.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -76,23 +76,23 @@
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir> <OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>

View File

@ -4,6 +4,11 @@
#define LOGGER Logger::GetLogger() #define LOGGER Logger::GetLogger()
void setLogDirectory(string m_dirPath)
{
LOGGER->setDirectory(m_dirPath);
}
void log(const string& message, bool addToJSON) void log(const string& message, bool addToJSON)
{ {
LOGGER->log(message, addToJSON); LOGGER->log(message, addToJSON);

View File

@ -8,25 +8,51 @@ const string Logger::m_sFileName = LOG_NAME;
Logger* Logger::m_pThis = NULL; Logger* Logger::m_pThis = NULL;
ofstream Logger::m_Logfile; ofstream Logger::m_Logfile;
std::map<unsigned long long, std::string> Logger::m_logs; std::map<unsigned long long, std::string> Logger::m_logs;
std::string Logger::m_dirPath;
Logger::Logger() Logger::Logger()
{ {
} }
Logger* Logger::GetLogger() Logger* Logger::GetLogger()
{ {
if (m_pThis == NULL) { if (m_pThis == NULL) {
m_pThis = new Logger(); m_pThis = new Logger();
std::filesystem::path dirPath = std::filesystem::temp_directory_path(); m_pThis->Clear();
m_Logfile.open((dirPath.string() + m_sFileName).c_str(), ios::out);
} }
return m_pThis; return m_pThis;
} }
void Logger::setDirectory(string newDirPath)
{
m_dirPath = newDirPath;
Clear();
}
void Logger::Clear()
{
lock_guard<mutex> guard(mutexLock);
try {
m_Logfile.open((m_dirPath + m_sFileName).c_str(), ios::out | ios::trunc);
}
catch (...) {
std::filesystem::path m_dirPath = std::filesystem::temp_directory_path();
m_Logfile.open((m_dirPath.string() + m_sFileName).c_str(), ios::out | ios::trunc);
}
m_Logfile << "Creating a new log instance\n";
m_pThis->Close();
}
void Logger::Open() void Logger::Open()
{ {
std::filesystem::path dirPath = std::filesystem::temp_directory_path(); try {
m_Logfile.open((dirPath.string() + m_sFileName).c_str(), ios::out | ios::app); m_Logfile.open((m_dirPath + m_sFileName).c_str(), ios::out | std::ios::app);
}
catch (...) {
std::filesystem::path m_dirPath = std::filesystem::temp_directory_path();
m_Logfile.open((m_dirPath.string() + m_sFileName).c_str(), ios::out | std::ios::app);
}
} }
void Logger::Close() void Logger::Close()

View File

@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 FILEVERSION 2,0,0,0
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -79,12 +79,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "DCS Olympus" VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus" VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "luatools.dll" VALUE "InternalName", "luatools.dll"
VALUE "LegalCopyright", "Copyright (C) 2023" VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "luatools.dll" VALUE "OriginalFilename", "luatools.dll"
VALUE "ProductName", "DCS Olympus" VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "ProductVersion", "2.0.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -60,23 +60,23 @@
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir> <OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>

View File

@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 FILEVERSION 2,0,0,0
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -79,12 +79,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "DCS Olympus" VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus" VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "olympus.dll" VALUE "InternalName", "olympus.dll"
VALUE "LegalCopyright", "Copyright (C) 2023" VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "olympus.dll" VALUE "OriginalFilename", "olympus.dll"
VALUE "ProductName", "DCS Olympus" VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "ProductVersion", "2.0.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -62,11 +62,11 @@
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\DCSOlympus.props" /> <Import Project="..\DCSOlympus.props" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -75,7 +75,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<OutDir>.\..\..\bin\</OutDir> <OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>

View File

@ -11,12 +11,16 @@ typedef int(__stdcall* f_coreFrame)(lua_State* L);
typedef int(__stdcall* f_coreUnitsData)(lua_State* L); typedef int(__stdcall* f_coreUnitsData)(lua_State* L);
typedef int(__stdcall* f_coreWeaponsData)(lua_State* L); typedef int(__stdcall* f_coreWeaponsData)(lua_State* L);
typedef int(__stdcall* f_coreMissionData)(lua_State* L); typedef int(__stdcall* f_coreMissionData)(lua_State* L);
typedef int(__stdcall* f_coreDrawingsData)(lua_State* L);
typedef int(__stdcall* f_coreSetExecutionResults)(lua_State* L);
f_coreInit coreInit = nullptr; f_coreInit coreInit = nullptr;
f_coreDeinit coreDeinit = nullptr; f_coreDeinit coreDeinit = nullptr;
f_coreFrame coreFrame = nullptr; f_coreFrame coreFrame = nullptr;
f_coreUnitsData coreUnitsData = nullptr; f_coreUnitsData coreUnitsData = nullptr;
f_coreWeaponsData coreWeaponsData = nullptr; f_coreWeaponsData coreWeaponsData = nullptr;
f_coreMissionData coreMissionData = nullptr; f_coreMissionData coreMissionData = nullptr;
f_coreDrawingsData coreDrawingsData = nullptr;
f_coreSetExecutionResults coreExecutionResults = nullptr;
string modPath; string modPath;
@ -49,6 +53,9 @@ static int onSimulationStart(lua_State* L)
{ {
LogInfo(L, "Trying to load core.dll from " + modPath); LogInfo(L, "Trying to load core.dll from " + modPath);
SetDllDirectoryA(modPath.c_str()); SetDllDirectoryA(modPath.c_str());
setLogDirectory(modPath);
log("onSimulationStart callback called successfully"); log("onSimulationStart callback called successfully");
string dllLocation = modPath + "\\core.dll"; string dllLocation = modPath + "\\core.dll";
@ -105,6 +112,20 @@ static int onSimulationStart(lua_State* L)
goto error; goto error;
} }
coreDrawingsData = (f_coreDrawingsData)GetProcAddress(hGetProcIDDLL, "coreDrawingsData");
if (!coreDrawingsData)
{
LogError(L, "Error getting coreDrawingsData ProcAddress from DLL");
goto error;
}
coreExecutionResults = (f_coreSetExecutionResults)GetProcAddress(hGetProcIDDLL, "coreSetExecutionResults");
if (!coreExecutionResults)
{
LogError(L, "Error getting coreSetExecutionResults ProcAddress from DLL");
goto error;
}
coreInit(L, modPath.c_str()); coreInit(L, modPath.c_str());
LogInfo(L, "Module loaded and started successfully."); LogInfo(L, "Module loaded and started successfully.");
@ -152,6 +173,8 @@ static int onSimulationStop(lua_State* L)
coreUnitsData = nullptr; coreUnitsData = nullptr;
coreWeaponsData = nullptr; coreWeaponsData = nullptr;
coreMissionData = nullptr; coreMissionData = nullptr;
coreDrawingsData = nullptr;
} }
hGetProcIDDLL = NULL; hGetProcIDDLL = NULL;
@ -190,6 +213,24 @@ static int setMissionData(lua_State* L)
return 0; return 0;
} }
static int setDrawingsData(lua_State* L)
{
if (coreDrawingsData)
{
coreDrawingsData(L);
}
return 0;
}
static int setExecutionResults(lua_State* L)
{
if (coreExecutionResults)
{
coreExecutionResults(L);
}
return 0;
}
static const luaL_Reg Map[] = { static const luaL_Reg Map[] = {
{"onSimulationStart", onSimulationStart}, {"onSimulationStart", onSimulationStart},
{"onSimulationFrame", onSimulationFrame}, {"onSimulationFrame", onSimulationFrame},
@ -197,6 +238,8 @@ static const luaL_Reg Map[] = {
{"setUnitsData", setUnitsData }, {"setUnitsData", setUnitsData },
{"setWeaponsData", setWeaponsData }, {"setWeaponsData", setWeaponsData },
{"setMissionData", setMissionData }, {"setMissionData", setMissionData },
{"setDrawingsData", setDrawingsData },
{"setExecutionResults", setExecutionResults },
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -0,0 +1,30 @@
#pragma once
#define VERSION "{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}"
#define LOG_NAME "..\\..\\..\\..\\Logs\\Olympus_log.txt"
#define REST_ADDRESS "http://localhost:3001"
#define REST_URI "olympus"
#define UNITS_URI "units"
#define WEAPONS_URI "weapons"
#define LOGS_URI "logs"
#define AIRBASES_URI "airbases"
#define BULLSEYE_URI "bullseyes"
#define SPOTS_URI "spots"
#define MISSION_URI "mission"
#define COMMANDS_URI "commands"
#define DRAWINGS_URI "drawings"
#define FRAMERATE_TIME_INTERVAL 0.05
#define OLYMPUS_JSON_PATH "..\\..\\..\\..\\Config\\olympus.json"
#define AIRCRAFT_DATABASE_PATH "..\\databases\\units\\aircraftdatabase.json"
#define HELICOPTER_DATABASE_PATH "..\\databases\\units\\helicopterdatabase.json"
#define GROUNDUNIT_DATABASE_PATH "..\\databases\\units\\groundunitdatabase.json"
#define NAVYUNIT_DATABASE_PATH "..\\databases\\units\\navyunitdatabase.json"
#define MIST_SCRIPT "..\\Scripts\\mist.lua"
#define OLYMPUS_COMMAND_SCRIPT "..\\Scripts\\OlympusCommand.lua"
#define UNIT_PAYLOADS_SCRIPT "..\\Scripts\\unitPayloads.lua"
#define TEMPLATES_SCRIPT "..\\Scripts\\templates.lua"
#define MODS_SCRIPT "..\\Scripts\\mods.lua"

View File

@ -6,6 +6,7 @@ struct Coords {
double lat = 0; double lat = 0;
double lng = 0; double lng = 0;
double alt = 0; double alt = 0;
double threshold = 0; // used for proximity checks only, not part of the actual coordinates
}; };
struct Offset { struct Offset {

View File

@ -1,5 +1,6 @@
#include "framework.h" #include "framework.h"
#include "utils.h" #include "utils.h"
#include <chrono>
// Get current date/time, format is YYYY-MM-DD.HH:mm:ss // Get current date/time, format is YYYY-MM-DD.HH:mm:ss
const std::string CurrentDateTime() const std::string CurrentDateTime()
@ -44,7 +45,11 @@ std::string to_string(const std::wstring& wstr)
std::string random_string(size_t length) std::string random_string(size_t length)
{ {
srand(static_cast<unsigned int>(time(NULL))); // Use nanoseconds since epoch as a seed for random number generation
auto now = std::chrono::high_resolution_clock::now();
auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
srand(static_cast<unsigned int>(nanos));
auto randchar = []() -> char auto randchar = []() -> char
{ {
const char charset[] = const char charset[] =
@ -59,9 +64,9 @@ std::string random_string(size_t length)
return str; return str;
} }
bool operator== (const Coords& a, const Coords& b) { return a.lat == b.lat && a.lng == b.lng && a.alt == b.alt; } bool operator== (const Coords& a, const Coords& b) { return a.lat == b.lat && a.lng == b.lng && a.alt == b.alt && a.threshold == b.threshold; }
bool operator!= (const Coords& a, const Coords& b) { return !(a == b); } bool operator!= (const Coords& a, const Coords& b) { return !(a == b); }
bool operator== (const Coords& a, const double& b) { return a.lat == b && a.lng == b && a.alt == b; } bool operator== (const Coords& a, const double& b) { return a.lat == b && a.lng == b && a.alt == b && a.threshold == b; }
bool operator!= (const Coords& a, const double& b) { return !(a == b); } bool operator!= (const Coords& a, const double& b) { return !(a == b); }
bool operator== (const Offset& a, const Offset& b) { return a.x == b.x && a.y == b.y && a.z == b.z; } bool operator== (const Offset& a, const Offset& b) { return a.x == b.x && a.y == b.y && a.z == b.z; }

View File

@ -61,8 +61,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 FILEVERSION 2,0,0,0
PRODUCTVERSION {{OLYMPUS_VS_VERSION_NUMBER_1}},0 PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -79,12 +79,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "DCS Olympus" VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus" VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "utils.dll" VALUE "InternalName", "utils.dll"
VALUE "LegalCopyright", "Copyright (C) 2023" VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "utils.dll" VALUE "OriginalFilename", "utils.dll"
VALUE "ProductName", "TODO: <Product name>" VALUE "ProductName", "TODO: <Product name>"
VALUE "ProductVersion", "{{OLYMPUS_VS_VERSION_NUMBER_2}}.0" VALUE "ProductVersion", "2.0.0.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -85,7 +85,7 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir> <OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir> <OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir>

View File

@ -0,0 +1,14 @@
{
"default-registry": {
"kind": "git",
"baseline": "7f9f0e44db287e8e67c0e888141bfa200ab45121",
"repository": "https://github.com/microsoft/vcpkg"
},
"registries": [
{
"kind": "artifact",
"location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
"name": "microsoft"
}
]
}

6
backend/vcpkg.json Normal file
View File

@ -0,0 +1,6 @@
{
"dependencies": [
"cpprestsdk",
"geographiclib"
]
}

View File

@ -1,23 +0,0 @@
call node increase_version.js
cd src
msbuild olympus.sln /t:Build /p:Configuration=Release
cd ..
cd client
rmdir /s /q "hgt"
call npm install
call npm run emit-declarations
call npm run build-release
cd "plugins\controltips"
call npm install
call npm run build-release
cd "..\.."
cd "plugins\databasemanager"
call npm install
call npm run build-release
cd "..\.."
cd..

View File

@ -1,2 +1,2 @@
call build.bat call .\scripts\batch\build.bat
call package.bat call .\scripts\batch\package.bat

View File

@ -1,2 +0,0 @@
{
}

File diff suppressed because it is too large Load Diff

View File

@ -1,49 +0,0 @@
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var fs = require('fs');
var bodyParser = require('body-parser');
var atcRouter = require('./routes/api/atc');
var airbasesRouter = require('./routes/api/airbases');
var elevationRouter = require('./routes/api/elevation');
var databasesRouter = require('./routes/api/databases');
var indexRouter = require('./routes/index');
var uikitRouter = require('./routes/uikit');
var usersRouter = require('./routes/users');
var resourcesRouter = require('./routes/resources');
var pluginsRouter = require('./routes/plugins');
var app = express();
app.use(logger('dev'));
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/api/atc', atcRouter);
app.use('/api/airbases', airbasesRouter);
app.use('/api/elevation', elevationRouter);
app.use('/api/databases', databasesRouter);
app.use('/plugins', pluginsRouter)
app.use('/users', usersRouter);
app.use('/uikit', uikitRouter);
app.use('/resources', resourcesRouter);
app.set('view engine', 'ejs');
let rawdata = fs.readFileSync('../olympus.json');
let config = JSON.parse(rawdata);
if (config["server"] != undefined)
app.get('/config', (req, res) => res.send(config["server"]));
module.exports = app;
const DemoDataGenerator = require('./demo.js');
var demoDataGenerator = new DemoDataGenerator(app, config);

View File

@ -1,118 +0,0 @@
#!/usr/bin/env node
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
console.log('\x1b[36m%s\x1b[0m', "* _____ _____ _____ ____ _ *");
console.log('\x1b[36m%s\x1b[0m', "* | __ \\ / ____|/ ____| / __ \\| | *");
console.log('\x1b[36m%s\x1b[0m', "* | | | | | | (___ | | | | |_ _ _ __ ___ _ __ _ _ ___ *");
console.log('\x1b[36m%s\x1b[0m', "* | | | | | \\___ \\ | | | | | | | | '_ ` _ \\| '_ \\| | | / __| *");
console.log('\x1b[36m%s\x1b[0m', "* | |__| | |____ ____) | | |__| | | |_| | | | | | | |_) | |_| \\__ \\ *");
console.log('\x1b[36m%s\x1b[0m', "* |_____/ \\_____|_____/ \\____/|_|\\__, |_| |_| |_| .__/ \\__,_|___/ *");
console.log('\x1b[36m%s\x1b[0m', "* __/ | | | *");
console.log('\x1b[36m%s\x1b[0m', "* |___/ |_| *");
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
console.log('\x1b[36m%s\x1b[0m', "");
console.log("Please wait while DCS Olympus Server starts up...");
var fs = require('fs');
let rawdata = fs.readFileSync('../olympus.json');
let config = JSON.parse(rawdata);
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('client:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var configPort = null;
if (config["client"] != undefined && config["client"]["port"] != undefined) {
configPort = config["client"]["port"];
}
var port = normalizePort(configPort || '3000');
app.set('port', port);
console.log("Express server listening on port: " + port)
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
console.log("DCS Olympus server {{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}} started correctly!")
console.log("Waiting for connections...")
process.title = `DCS Olympus server {{OLYMPUS_VERSION_NUMBER}} (${port})`;

View File

@ -1,117 +0,0 @@
const fs = require('fs')
const path = require('path')
const yargs = require('yargs');
const prompt = require('prompt-sync')({sigint: true});
const sha256 = require('sha256');
const jsonPath = path.join('..', 'olympus.json');
/* Set the acceptable values */
yargs.alias('a', 'address').describe('a', 'Backend address').string('a');
yargs.alias('b', 'backendPort').describe('b', 'Backend port').number('b');
yargs.alias('c', 'clientPort').describe('c', 'Client port').number('c');
yargs.alias('p', 'gameMasterPassword').describe('p', 'Game Master password').string('p');
yargs.alias('bp', 'blueCommanderPassword').describe('bp', 'Blue Commander password').string('bp');
yargs.alias('rp', 'redCommanderPassword').describe('rp', 'Red Commander password').string('rp');
args = yargs.argv;
async function run() {
/* Check that we can read the json */
if (fs.existsSync(jsonPath)) {
var json = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
var address = args.address ?? json["server"]["address"];
var clientPort = args.clientPort ?? json["client"]["port"];
var backendPort = args.backendPort ?? json["server"]["port"];
var gameMasterPassword = args.gameMasterPassword? sha256(args.gameMasterPassword): json["authentication"]["gameMasterPassword"];
var blueCommanderPassword = args.blueCommanderPassword? sha256(args.blueCommanderPassword): json["authentication"]["blueCommanderPassword"];
var redCommanderPassword = args.redCommanderPassword? sha256(args.redCommanderPassword): json["authentication"]["redCommanderPassword"];
/* Run in interactive mode */
if (args.address === undefined && args.clientPort === undefined && args.backendPort === undefined &&
args.gameMasterPassword === undefined && args.blueCommanderPassword === undefined && args.redCommanderPassword === undefined) {
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
console.log('\x1b[36m%s\x1b[0m', "* _____ _____ _____ ____ _ *");
console.log('\x1b[36m%s\x1b[0m', "* | __ \\ / ____|/ ____| / __ \\| | *");
console.log('\x1b[36m%s\x1b[0m', "* | | | | | | (___ | | | | |_ _ _ __ ___ _ __ _ _ ___ *");
console.log('\x1b[36m%s\x1b[0m', "* | | | | | \\___ \\ | | | | | | | | '_ ` _ \\| '_ \\| | | / __| *");
console.log('\x1b[36m%s\x1b[0m', "* | |__| | |____ ____) | | |__| | | |_| | | | | | | |_) | |_| \\__ \\ *");
console.log('\x1b[36m%s\x1b[0m', "* |_____/ \\_____|_____/ \\____/|_|\\__, |_| |_| |_| .__/ \\__,_|___/ *");
console.log('\x1b[36m%s\x1b[0m', "* __/ | | | *");
console.log('\x1b[36m%s\x1b[0m', "* |___/ |_| *");
console.log('\x1b[36m%s\x1b[0m', "*********************************************************************");
console.log('\x1b[36m%s\x1b[0m', "");
console.log("DCS Olympus configurator {{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}");
console.log("");
var newValue;
var result;
/* Get the new address */
newValue = prompt(`Insert an address or press Enter to keep current value ${address}. Use * for any address: `);
address = newValue !== ""? newValue: address;
/* Get the new client port */
while (true) {
newValue = prompt(`Insert a client port or press Enter to keep current value ${clientPort}. Integers between 1025 and 65535: `);
if (newValue === "")
break;
result = Number(newValue);
if (!isNaN(result) && Number.isInteger(result) && result > 1024 && result <= 65535)
break;
}
clientPort = newValue? result: clientPort;
/* Get the new backend port */
while (true) {
newValue = prompt(`Insert a backend port or press Enter to keep current value ${backendPort}. Integers between 1025 and 65535: `);
if (newValue === "")
break;
result = Number(newValue);
if (!isNaN(result) && Number.isInteger(result) && result > 1024 && result <= 65535 && result != clientPort)
break;
if (result === clientPort)
console.log("Client port and backend port must be different.");
}
backendPort = newValue? result: backendPort;
/* Get the new Game Master password */
newValue = prompt(`Insert a new Game Master password or press Enter to keep current value: `, {echo: "*"});
gameMasterPassword = newValue !== ""? sha256(newValue): gameMasterPassword;
/* Get the new Blue Commander password */
newValue = prompt(`Insert a new Blue Commander password or press Enter to keep current value: `, {echo: "*"});
blueCommanderPassword = newValue !== ""? sha256(newValue): blueCommanderPassword;
/* Get the new Red Commander password */
newValue = prompt(`Insert a new Red Commander password or press Enter to keep current value: `, {echo: "*"});
redCommanderPassword = newValue !== ""? sha256(newValue): redCommanderPassword;
}
/* Apply the inputs */
json["server"]["address"] = address;
json["client"]["port"] = clientPort;
json["server"]["port"] = backendPort;
json["authentication"]["gameMasterPassword"] = gameMasterPassword;
json["authentication"]["blueCommanderPassword"] = blueCommanderPassword;
json["authentication"]["redCommanderPassword"] = redCommanderPassword;
/* Write the result to disk */
const serialized = JSON.stringify(json, null, 4);
fs.writeFileSync(jsonPath, serialized, 'utf8');
console.log("Olympus.json updated correctly, goodbye!");
}
else {
console.error("Error, could not read olympus.json file!")
}
/* Wait a bit before closing the window */
await new Promise(resolve => setTimeout(resolve, 3000));
}
/* Run the configurator */
run();

View File

@ -1,4 +0,0 @@
copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet\\leaflet.css
copy .\\node_modules\\leaflet-gesture-handling\\dist\\leaflet-gesture-handling.css .\\public\\stylesheets\\leaflet\\leaflet-gesture-handling.css
copy .\\node_modules\\leaflet.nauticscale\\dist\\leaflet.nauticscale.js .\\public\\javascripts\\leaflet.nauticscale.js
copy .\\node_modules\\leaflet-path-drag\\dist\\L.Path.Drag.js .\\public\\javascripts\\L.Path.Drag.js

View File

@ -1,2 +0,0 @@
start cmd /k "npm run start"
start cmd /k "watchify .\src\index.ts --debug -o .\public\javascripts\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]

View File

@ -1,514 +0,0 @@
const { random } = require('@turf/turf');
var basicAuth = require('express-basic-auth')
var enc = new TextEncoder();
const aircraftDatabase = require('./public/databases/units/aircraftDatabase.json');
const helicopterDatabase = require('./public/databases/units/helicopterDatabase.json');
const groundUnitDatabase = require('./public/databases/units/groundUnitDatabase.json');
const navyUnitDatabase = require('./public/databases/units/navyUnitDatabase.json');
const DEMO_UNIT_DATA = {}
const DEMO_WEAPONS_DATA = {
/*["1001"]:{ category: "Missile", alive: true, coalition: 2, name: "", position: { lat: 37.1, lng: -116, alt: 1000 }, speed: 200, heading: 45 * Math.PI / 180 }, */
}
class DemoDataGenerator {
constructor(app, config)
{
app.get('/demo/units', (req, res) => this.units(req, res));
app.get('/demo/weapons', (req, res) => this.weapons(req, res));
app.get('/demo/logs', (req, res) => this.logs(req, res));
app.get('/demo/bullseyes', (req, res) => this.bullseyes(req, res));
app.get('/demo/airbases', (req, res) => this.airbases(req, res));
app.get('/demo/mission', (req, res) => this.mission(req, res));
app.get('/demo/commands', (req, res) => this.command(req, res));
app.put('/demo', (req, res) => this.put(req, res));
app.use('/demo', basicAuth({
users: {
'admin': config["authentication"]["gameMasterPassword"],
'blue': config["authentication"]["blueCommanderPassword"],
'red': config["authentication"]["redCommanderPassword"]
},
}))
let baseData = { alive: true, human: false, controlled: true, coalition: 2, country: 0, unitName: "Cool guy", groupName: "Cool group 1", state: 13, task: "Being cool!",
hasTask: true, position: { lat: 37, lng: -116, alt: 1000 }, speed: 200, horizontalVelocity: 200, verticalVelicity: 0, heading: 45, track: 45, isActiveTanker: false, isActiveAWACS: false, onOff: true, followRoads: false, fuel: 50,
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
formationOffset: { x: 0, y: 0, z: 0 },
targetID: 0,
targetPosition: { lat: 0, lng: 0, alt: 0 },
ROE: 1,
reactionToThreat: 1,
emissionsCountermeasures: 1,
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
ammo: [],
contacts: [],
activePath: [],
isLeader: true
}
// UNCOMMENT TO TEST ALL UNITS ****************
/*
var databases = Object.assign({}, aircraftDatabase, helicopterDatabase, groundUnitDatabase, navyUnitDatabase);
var t = Object.keys(databases).length;
var l = Math.floor(Math.sqrt(t));
let latIdx = 0;
let lngIdx = 0;
let idx = 1;
console.log(l)
for (let name in databases) {
if (databases[name].enabled) {
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
DEMO_UNIT_DATA[idx].name = name;
DEMO_UNIT_DATA[idx].groupName = `Group-${idx}`;
DEMO_UNIT_DATA[idx].position.lat += latIdx / 5;
DEMO_UNIT_DATA[idx].position.lng += lngIdx / 5;
DEMO_UNIT_DATA[idx].coalition = Math.floor(Math.random() * 3)
latIdx += 1;
if (latIdx === l) {
latIdx = 0;
lngIdx += 1;
}
if (name in aircraftDatabase)
DEMO_UNIT_DATA[idx].category = "Aircraft";
else if (name in helicopterDatabase)
DEMO_UNIT_DATA[idx].category = "Helicopter";
else if (name in groundUnitDatabase)
DEMO_UNIT_DATA[idx].category = "GroundUnit";
else if (name in navyUnitDatabase)
DEMO_UNIT_DATA[idx].category = "NavyUnit";
idx += 1;
}
}
*/
let idx = 1;
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
DEMO_UNIT_DATA[idx].name = "S_75M_Volhov";
DEMO_UNIT_DATA[idx].groupName = `Group`;
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
DEMO_UNIT_DATA[idx].category = "GroundUnit";
DEMO_UNIT_DATA[idx].isLeader = true;
idx += 1;
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
DEMO_UNIT_DATA[idx].name = "SNR_75V";
DEMO_UNIT_DATA[idx].groupName = `Group`;
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
DEMO_UNIT_DATA[idx].category = "GroundUnit";
DEMO_UNIT_DATA[idx].isLeader = false;
idx += 1;
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
DEMO_UNIT_DATA[idx].name = "Ural-4320 APA-5D";
DEMO_UNIT_DATA[idx].groupName = `Group`;
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
DEMO_UNIT_DATA[idx].category = "GroundUnit";
DEMO_UNIT_DATA[idx].isLeader = false;
idx += 1;
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
DEMO_UNIT_DATA[idx].name = "F-14B";
DEMO_UNIT_DATA[idx].groupName = `Group-1`;
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
DEMO_UNIT_DATA[idx].category = "Aircraft";
DEMO_UNIT_DATA[idx].isLeader = false;
idx += 1;
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
DEMO_UNIT_DATA[idx].name = "Infantry AK";
DEMO_UNIT_DATA[idx].groupName = `Group-2`;
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
DEMO_UNIT_DATA[idx].category = "GroundUnit";
DEMO_UNIT_DATA[idx].isLeader = true;
DEMO_UNIT_DATA[idx].coalition = 0;
DEMO_UNIT_DATA[idx].operateAs = 2;
idx += 1;
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
DEMO_UNIT_DATA[idx].name = "Infantry AK";
DEMO_UNIT_DATA[idx].groupName = `Group-3`;
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
DEMO_UNIT_DATA[idx].category = "GroundUnit";
DEMO_UNIT_DATA[idx].isLeader = true;
DEMO_UNIT_DATA[idx].coalition = 0;
DEMO_UNIT_DATA[idx].operateAs = 1;
idx += 1;
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
DEMO_UNIT_DATA[idx].name = "KC-135";
DEMO_UNIT_DATA[idx].groupName = `Group-4`;
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
DEMO_UNIT_DATA[idx].category = "Aircraft";
DEMO_UNIT_DATA[idx].isLeader = true;
this.startTime = Date.now();
}
units(req, res){
var array = new Uint8Array();
var time = Date.now();
array = this.concat(array, this.uint64ToByteArray(BigInt(time)));
if (req.query["time"] == 0){
for (let idx in DEMO_UNIT_DATA) {
const unit = DEMO_UNIT_DATA[idx];
var dataIndex = 1;
array = this.concat(array, this.uint32ToByteArray(idx));
array = this.appendString(array, unit.category, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.alive, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.human, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.controlled, dataIndex); dataIndex++;
array = this.appendUint16(array, unit.coalition, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.country, dataIndex); dataIndex++;
array = this.appendString(array, unit.name, dataIndex); dataIndex++;
array = this.appendString(array, unit.unitName, dataIndex); dataIndex++;
array = this.appendString(array, unit.groupName, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.state, dataIndex); dataIndex++;
array = this.appendString(array, unit.task, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.hasTask, dataIndex); dataIndex++;
array = this.appendCoordinates(array, unit.position, dataIndex); dataIndex++;
array = this.appendDouble(array, unit.speed, dataIndex); dataIndex++;
array = this.appendDouble(array, unit.horizontalVelocity, dataIndex); dataIndex++;
array = this.appendDouble(array, unit.verticalVelicity, dataIndex); dataIndex++;
array = this.appendDouble(array, unit.heading, dataIndex); dataIndex++;
array = this.appendDouble(array, unit.track, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.isActiveTanker, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.isActiveAWACS, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.onOff, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.followRoads, dataIndex); dataIndex++;
array = this.appendUint16(array, unit.fuel, dataIndex); dataIndex++;
array = this.appendDouble(array, unit.desiredSpeed, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.desiredSpeedType, dataIndex); dataIndex++;
array = this.appendDouble(array, unit.desiredAltitude, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.desiredAltitudeType, dataIndex); dataIndex++;
array = this.appendUint32(array, unit.leaderID, dataIndex); dataIndex++;
array = this.appendOffset(array, unit.formationOffset, dataIndex); dataIndex++;
array = this.appendUint32(array, unit.targetID, dataIndex); dataIndex++;
array = this.appendCoordinates(array, unit.targetPosition, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.ROE, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.reactionToThreat, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.emissionsCountermeasures, dataIndex); dataIndex++;
array = this.appendTACAN(array, unit.TACAN, dataIndex); dataIndex++;
array = this.appendRadio(array, unit.radio, dataIndex); dataIndex++;
array = this.appendRadio(array, unit.generalSettings, dataIndex); dataIndex++;
array = this.appendAmmo(array, unit.ammo, dataIndex); dataIndex++;
array = this.appendContacts(array, unit.contacts, dataIndex); dataIndex++;
array = this.appendActivePath(array, unit.activePath, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.isLeader, dataIndex); dataIndex++;
array = this.appendUint8(array, unit.operateAs, dataIndex); dataIndex++;
array = this.concat(array, this.uint8ToByteArray(255));
}
}
res.end(Buffer.from(array, 'binary'));
};
weapons(req, res){
var array = new Uint8Array();
var time = Date.now();
array = this.concat(array, this.uint64ToByteArray(BigInt(time)));
for (let idx in DEMO_WEAPONS_DATA) {
const weapon = DEMO_WEAPONS_DATA[idx];
array = this.concat(array, this.uint32ToByteArray(idx));
array = this.appendString(array, weapon.category, 1);
array = this.appendUint8(array, weapon.alive, 2);
array = this.appendUint16(array, weapon.coalition, 5);
array = this.appendString(array, weapon.name, 7);
array = this.appendCoordinates(array, weapon.position, 13);
array = this.appendDouble(array, weapon.speed, 14);
array = this.appendDouble(array, weapon.heading, 15);
array = this.concat(array, this.uint8ToByteArray(255));
}
res.end(Buffer.from(array, 'binary'));
};
concat(array1, array2) {
var mergedArray = new Uint8Array(array1.length + array2.length);
mergedArray.set(array1);
mergedArray.set(array2, array1.length);
return mergedArray;
}
uint8ToByteArray(number) {
var buffer = new ArrayBuffer(1);
var longNum = new Uint8Array(buffer);
longNum[0] = number;
return Array.from(new Uint8Array(buffer));
}
uint16ToByteArray(number) {
var buffer = new ArrayBuffer(2);
var longNum = new Uint16Array(buffer);
longNum[0] = number;
return Array.from(new Uint8Array(buffer));
}
uint32ToByteArray(number) {
var buffer = new ArrayBuffer(4);
var longNum = new Uint32Array(buffer);
longNum[0] = number;
return Array.from(new Uint8Array(buffer));
}
uint64ToByteArray(number) {
var buffer = new ArrayBuffer(8);
var longNum = new BigUint64Array(buffer);
longNum[0] = number;
return Array.from(new Uint8Array(buffer));
}
doubleToByteArray(number) {
var buffer = new ArrayBuffer(8);
var longNum = new Float64Array(buffer);
longNum[0] = number;
return Array.from(new Uint8Array(buffer));
}
appendUint8(array, number, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint8ToByteArray(number));
return array;
}
appendUint16(array, number, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint16ToByteArray(number));
return array;
}
appendUint32(array, number, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint32ToByteArray(number));
return array;
}
appendDouble(array, number, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.doubleToByteArray(number));
return array;
}
appendCoordinates(array, coordinates, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.doubleToByteArray(coordinates.lat));
array = this.concat(array, this.doubleToByteArray(coordinates.lng));
array = this.concat(array, this.doubleToByteArray(coordinates.alt));
return array;
}
appendOffset(array, offset, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.doubleToByteArray(offset.x));
array = this.concat(array, this.doubleToByteArray(offset.y));
array = this.concat(array, this.doubleToByteArray(offset.z));
return array;
}
appendString(array, string, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint16ToByteArray(string.length));
array = this.concat(array, enc.encode(string));
return array;
}
padString(string, length) {
while (string.length < length)
string += " ";
return string.substring(0, length);
}
appendTACAN(array, TACAN, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint8ToByteArray(TACAN.isOn));
array = this.concat(array, this.uint8ToByteArray(TACAN.channel));
array = this.concat(array, enc.encode(TACAN.XY));
array = this.concat(array, enc.encode(this.padString(TACAN.callsign, 4)));
return array;
}
appendRadio(array, radio, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint32ToByteArray(radio.frequency));
array = this.concat(array, this.uint8ToByteArray(radio.callsign));
array = this.concat(array, this.uint8ToByteArray(radio.callsignNumber));
return array;
}
appendGeneralSettings(array, generalSettings, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitAA));
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitAfterburner));
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitAG));
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitAirWpn));
array = this.concat(array, this.uint8ToByteArray(generalSettings.prohibitJettison));
return array;
}
appendAmmo(array, ammo, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint16ToByteArray(ammo.length));
ammo.forEach((element) => {
array = this.concat(array, this.uint16ToByteArray(element.quantity));
array = this.concat(array, enc.encode(this.padString(element.name, 33)));
array = this.concat(array, this.uint8ToByteArray(element.guidance));
array = this.concat(array, this.uint8ToByteArray(element.category));
array = this.concat(array, this.uint8ToByteArray(element.missileCategory));
})
return array;
}
appendContacts(array, contacts, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint16ToByteArray(contacts.length));
contacts.forEach((element) => {
array = this.concat(array, this.uint32ToByteArray(element.ID));
array = this.concat(array, this.uint8ToByteArray(element.detectionMethod));
})
return array;
}
appendActivePath(array, activePath, datumIndex) {
array = this.concat(array, this.uint8ToByteArray(datumIndex));
array = this.concat(array, this.uint16ToByteArray(activePath.length));
activePath.forEach((element) => {
array = this.concat(array, this.doubleToByteArray(element.lat));
array = this.concat(array, this.doubleToByteArray(element.lng));
array = this.concat(array, this.doubleToByteArray(element.alt));
})
return array;
}
logs(req, res){
var ret = {logs: {"1": "I'm a log!", "2": "I'm a different log!"}};
ret.time = Date.now();
ret.frameRate = 60;
ret.load = 0;
res.send(JSON.stringify(ret));
};
airbases(req, res){
var ret = {airbases: {
["0"]: {
callsign: "Nellis",
latitude: 37.3,
longitude: -115.8,
coalition: "neutral"
},
["1"]: {
callsign: "Red",
latitude: 37.3,
longitude: -115.75,
coalition: "red"
},
["2"]: {
callsign: "Blue",
latitude: 37.3,
longitude: -115.7,
coalition: "blue"
}
}};
ret.time = Date.now();
res.send(JSON.stringify(ret));
};
bullseyes(req, res){
var ret = {bullseyes: {
"0": {
latitude: 37.25,
longitude: -115.8,
coalition: "neutral"
},
"1": {
latitude: 37.25,
longitude: -115.75,
coalition: "red"
},
"2": {
latitude: 37.25,
longitude: -115.7,
coalition: "blue"
}
}};
ret.time = Date.now();
res.send(JSON.stringify(ret));
};
mission(req, res){
var ret = {mission: {theatre: "Nevada"}};
ret.time = Date.now();
ret.mission.dateAndTime = {
time: { h: 10, m: 15, s: 34 },
date: "",
elapsedTime: (Date.now() - this.startTime) / 1000,
startTime: 0
}
ret.mission.coalitions = {
red: [
'RUSSIA',
'CHINA'
],
blue: [
'UK',
'USA'
],
neutral: [
'ITALY'
]
}
ret.mission.commandModeOptions = {
restrictSpawns: true,
restrictToCoalition: true,
setupTime: 0,
spawnPoints: {
red: 400,
blue: 400
},
eras: ["WW2", "Early Cold War", "Late Cold War", "Modern"]
}
var auth = req.get("Authorization");
if (auth) {
var username = Buffer.from(auth.replace("Basic ", ""), 'base64').toString('binary').split(":")[0];
switch (username) {
case "admin":
ret.mission.commandModeOptions.commandMode = "Game master";
break
case "blue":
ret.mission.commandModeOptions.commandMode = "Blue commander";
break;
case "red":
ret.mission.commandModeOptions.commandMode = "Red commander";
break;
}
}
res.send(JSON.stringify(ret));
}
command(req, res) {
var ret = {commandExecuted: Math.random() > 0.5};
res.send(JSON.stringify(ret));
}
put(req, res) {
var ret = {commandHash: Math.random().toString(36).slice(2, 19)}
res.send(JSON.stringify(ret));
}
}
module.exports = DemoDataGenerator;

View File

@ -1,2 +0,0 @@
call npm install --omit=dev
call npm install yargs prompt-sync sha256 tcp-ping-port

8986
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +0,0 @@
{
"name": "DCSOlympus",
"node-main": "./bin/www",
"main": "http://localhost:3000",
"version": "{{OLYMPUS_VERSION_NUMBER}}",
"private": true,
"scripts": {
"build": "browserify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ] && copy.bat",
"build-release": "browserify .\\src\\index.ts -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ] && copy.bat",
"emit-declarations": "tsc --project tsconfig.json --declaration --emitDeclarationOnly --outfile ./@types/olympus/index.d.ts",
"copy": "copy.bat",
"start": "node ./bin/www",
"debug": "npm run copy & concurrently --kill-others \"npm run watch\" \"nodemon --ignore ./public/databases/ ./bin/www\"",
"watch": "watchify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]"
},
"dependencies": {
"@turf/turf": "^6.5.0",
"body-parser": "^1.20.2",
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"ejs": "^3.1.8",
"express": "~4.16.1",
"express-basic-auth": "^1.2.1",
"js-sha256": "^0.10.1",
"leaflet-gesture-handling": "^1.2.2",
"morgan": "~1.9.1",
"save": "^2.9.0",
"srtm-elevation": "^2.1.2",
"uuid": "^9.0.1"
},
"devDependencies": {
"@babel/preset-env": "^7.21.4",
"@tanem/svg-injector": "^10.1.68",
"@types/formatcoords": "^1.1.0",
"@types/geojson": "^7946.0.10",
"@types/leaflet": "^1.9.0",
"@types/node": "^18.16.1",
"@types/sortablejs": "^1.15.0",
"@types/svg-injector": "^0.0.29",
"babelify": "^10.0.0",
"browserify": "^17.0.0",
"concurrently": "^7.6.0",
"cp": "^0.2.0",
"esmify": "^2.1.1",
"formatcoords": "^1.1.3",
"geodesy": "^1.1.2",
"leaflet": "^1.9.3",
"leaflet-control-mini-map": "^0.4.0",
"leaflet-path-drag": "*",
"leaflet.nauticscale": "^1.1.0",
"nodemon": "^2.0.20",
"requirejs": "^2.3.6",
"sortablejs": "^1.15.0",
"tinyify": "^4.0.0",
"tsify": "^5.0.4",
"tslib": "latest",
"typescript": "^4.9.4",
"usng.js": "^0.4.5",
"watchify": "^4.0.0"
},
"window": {
"width": 1000,
"height": 800,
"position": "center",
"icon": "public/images/icon.png"
}
}

View File

@ -1,8 +0,0 @@
mkdir .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin
copy .\\index.js .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\index.js
copy .\\plugin.json .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\plugin.json
copy .\\style.css .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\style.css
mkdir .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\images
copy .\\images\\*.* .\\..\\DCSOlympus\\client\\public\\plugins\\boilerplateplugin\\images\\

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

View File

@ -1,14 +0,0 @@
{
"name": "boilerplateplugin",
"version": "v0.0.1",
"private": true,
"scripts": {
"build": "browserify ./src/index.ts -p [ tsify --noImplicitAny] > index.js && copy.bat"
},
"devDependencies": {
"@types/sortablejs": "^1.15.4",
"browserify": "^17.0.0",
"sortablejs": "^1.15.0",
"tsify": "^5.0.4"
}
}

View File

@ -1,7 +0,0 @@
{
"name": "Boilerplate",
"version": "0.0.1",
"description": "Base plugin starter",
"authorName": "",
"authorContact": ""
}

View File

@ -1,3 +0,0 @@
# Boilerplate plugin
See: https://github.com/Pax1601/DCSOlympus/wiki/Developer-Guide

View File

@ -1,27 +0,0 @@
import { OlympusPlugin } from "interfaces";
import { OlympusApp } from "olympusapp";
export class BoilerplatePlugin implements OlympusPlugin {
#app!: OlympusApp;
constructor() {
}
/**
* @param app <OlympusApp>
*
* @returns boolean on success/fail
*/
initialize(app: OlympusApp) : boolean {
this.#app = app;
return true; // Return true on success
}
getName() {
return "Boilerplate";
}
}

View File

@ -1,5 +0,0 @@
import { BoilerplatePlugin } from "./boilerplate";
globalThis.getOlympusPlugin = () => {
return new BoilerplatePlugin();
}

View File

@ -1,104 +0,0 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "ES2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"rootDirs": ["./src", "./@types"], /* Specify the root folder within your source files. */
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
"typeRoots": [
"./node_modules/@types",
"@types"
], /* Specify multiple folders that act like './node_modules/@types'. */
"types": [
"olympus"
], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": [
"src/*.ts",
"../DCSOlympus/client/@types/olympus/index.d.ts"
]
}

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