1615 Commits

Author SHA1 Message Date
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
Pax1601
2c403a9283 Fixed versioning tag 2023-12-14 17:39:42 +01:00
Pax1601
27c78d6a67 Update increase_version.js
Update increase_version.js

Update increase_version.js
2023-12-14 11:24:40 +01:00
Pax1601
e0d33760e0 Update increase_version.js 2023-12-14 11:11:16 +01:00
Pax1601
2d339d7161 Added version tag
Update increase_version.js

Update increase_version.js

Update increase_version.js

Create increase_version.js

Updated workflows

Update .gitignore

Update build.bat

Change hash string

Update increase_version.js

Added commit hash

v1.0.3
2023-12-14 11:04:22 +01:00
Pax1601
243f58ecf3 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-13 22:07:09 +01:00
Pax1601
378dbfc085 Fixed excessively high CPU load 2023-12-13 22:06:51 +01:00
Pax1601
cee6839b5d Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-13 17:47:24 +01:00
Pax1601
f1a836c222 Update olympus.iss 2023-12-13 17:47:13 +01:00
Pax1601
cbf4b56ecb Update msbuild.yml 2023-12-13 17:39:18 +01:00
Pax1601
e2e3da6a0f Update msbuild.yml 2023-12-13 17:37:11 +01:00
Pax1601
3a96808aa5 Update msbuild.yml 2023-12-13 17:36:05 +01:00
Pax1601
d1ccccae18 Update package.bat 2023-12-13 17:35:55 +01:00
Pax1601
d31242124f Update msbuild.yml 2023-12-13 17:14:37 +01:00
Pax1601
8c4996f466 Update msbuild.yml 2023-12-13 17:02:09 +01:00
Pax1601
59b89dc638 Update msbuild.yml 2023-12-13 16:54:56 +01:00
Pax1601
f54ac5c3d8 Update msbuild.yml 2023-12-13 16:53:02 +01:00
Pax1601
666b3e0383 Update msbuild.yml 2023-12-13 16:47:32 +01:00
Pax1601
d8893e21a1 Update msbuild.yml 2023-12-13 16:45:43 +01:00
Pax1601
5391b567b9 Updated workflows 2023-12-13 16:37:37 +01:00
Pax1601
ad7ea014f2 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-13 16:36:04 +01:00
Pax1601
ceb00a239f Added vcpkg manifest 2023-12-13 16:35:42 +01:00
Pax1601
81ab1aa05d Update msbuild.yml 2023-12-13 16:13:19 +01:00
Pax1601
7bf232f146 Update msbuild.yml 2023-12-13 16:10:21 +01:00
Pax1601
3f07271931 Update msbuild.yml 2023-12-13 16:07:54 +01:00
Pax1601
1c30bb006b Merge pull request #711 from Pax1601/CI-tests
Create msbuild.yml
2023-12-13 16:04:45 +01:00
Pax1601
34594ac836 Create msbuild.yml 2023-12-13 16:02:53 +01:00
Pax1601
cee58800e1 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-13 15:18:32 +01:00
Pax1601
ab3b487024 Added doxygen info 2023-12-13 15:18:23 +01:00
Pax1601
91b393eb35 Update ci.yml 2023-12-13 15:00:21 +01:00
Pax1601
edb4ddc287 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-13 15:00:11 +01:00
Pax1601
f9fd5caa9f Updated Doxygen config 2023-12-13 14:59:48 +01:00
Pax1601
d5653a9b1d Added doxygen config file 2023-12-13 14:51:31 +01:00
Pax1601
ec5ff1bf0c Merge pull request #710 from Pax1601/change-LEGAL-extension
Rename LEGAL to LEGAL.txt
2023-12-13 14:47:21 +01:00
Shredmetal
41912d1057 Rename LEGAL to LEGAL.txt 2023-12-13 02:45:30 +08:00
Pax1601
228452fd17 More installer upgrades 2023-12-12 17:34:43 +01:00
Pax1601
484d3dd28f Removed node bundling 2023-12-12 15:02:39 +01:00
Pax1601
a52e7e7b1a Added resource files 2023-12-12 11:39:28 +01:00
Pax1601
92a08f6278 Updated installer 2023-12-12 11:35:15 +01:00
Pax1601
8e3da65433 Added missing bat 2023-12-12 11:04:02 +01:00
Pax1601
3f625c03b9 Compilation scripts updated 2023-12-12 10:45:44 +01:00
Pax1601
4423d5f3d5 v1.0.2 2023-12-12 10:34:25 +01:00
Pax1601
d0fc286c43 v1.0.1 2023-12-11 20:28:38 +01:00
Pax1601
b5443ab0a8 Removed python configurator 2023-12-11 19:48:19 +01:00
Pax1601
e6c34306c9 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-11 19:45:03 +01:00
Pax1601
532a83fe91 Added c++ configurator 2023-12-11 19:44:58 +01:00
Pax1601
293b928764 Update README.md 2023-12-11 10:23:35 +01:00
Pax1601
38d62df75d Update README.md 2023-12-11 10:22:53 +01:00
Pax1601
fbd42ade6e Added window icon 2023-12-10 20:56:19 +01:00
Pax1601
9af1cffe08 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-10 20:36:33 +01:00
Pax1601
b0d92906e5 Fixed incorrect target management for mop and sff 2023-12-10 20:36:28 +01:00
Pax1601
0329e27713 Added ability to force coalition unit in IADS spawner 2023-12-10 20:33:13 +01:00
Pax1601
2d39862b1b Merge pull request #702 from Pax1601/691-pg-missing-airbase-data
691 pg missing airbase data
2023-12-10 20:26:06 +01:00
PeekabooSteam
5c1782ec7f Airbase tweaks, added thechannel.json 2023-12-10 17:53:23 +00:00
Pax1601
6c6117aee3 Fixed minor UI problems 2023-12-10 18:36:25 +01:00
Pax1601
1798e62315 v1.0.0 2023-12-10 18:36:03 +01:00
Pax1601
2b2ed76aa3 Updated databases 2023-12-10 18:35:23 +01:00
PeekabooSteam
38d72a5cd0 Allowed new theatres in API 2023-12-10 17:25:52 +00:00
PeekabooSteam
14ec4a8610 Added Normandy. 2023-12-10 17:23:39 +00:00
PeekabooSteam
bdc7a5bb46 Added Falklands map and Sinaimap map. 2023-12-10 16:29:47 +00:00
Pax1601
131f30405c Merge pull request #693 from Pax1601/ArtificialDogma-patch-1
Update README.md
2023-12-10 11:07:49 +01:00
Pax1601
dbf21e0af9 Merge pull request #694 from Pax1601/684-add-the-spitfire-and-loadouts
684 add the spitfire and loadouts
2023-12-10 11:07:27 +01:00
bobprofisker
9094f8fdc6 forgot to remove stupid wing colour BF-109 2023-12-09 20:49:17 +00:00
bobprofisker
aa0b0a585c Updated databases for spitfire, misc units and helos
Updated databases for spitfire, misc units and helos
2023-12-09 20:34:10 +00:00
bobprofisker
ad61037452 New unit payloads for spit
New unit payloads for spit, also includes clipped wing version
2023-12-09 20:32:52 +00:00
PeekabooSteam
66ed1a99e0 Corrected airbase names for PG 2023-12-09 19:52:00 +00:00
Pax1601
d7dc5769a8 Bugfixing, switched to human name for humans 2023-12-09 18:06:47 +01:00
Pax1601
b0ee653bff Fixed unabled to copy humans 2023-12-09 15:51:16 +01:00
Dogma
5a950e22ce Update README.md 2023-12-09 21:24:34 +11:00
Pax1601
0459d5c625 v0.4.13-alpha-rc5 2023-12-08 15:38:56 +01:00
Pax1601
43d28ebe19 Removed notify and added warning follow roads 2023-12-08 14:27:16 +01:00
Pax1601
187b9be57a Added ability to add mods 2023-12-08 11:54:12 +01:00
Pax1601
564a650403 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-07 15:49:31 +01:00
Pax1601
0e403e8b74 v0.4.12-alpha-rc4 2023-12-07 15:49:27 +01:00
Pax1601
840cdd9049 Update README.md 2023-12-07 15:39:48 +01:00
Pax1601
e5e7e9be14 Added increased load for onRoad movement 2023-12-07 15:22:59 +01:00
Pax1601
e677968ba7 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-07 15:08:01 +01:00
Pax1601
d24b955d52 Multiple bugfixes 2023-12-07 15:07:57 +01:00
Pax1601
48860ff514 Merge pull request #677 from Pax1601/674-airbases-visibility-button-still-dark-when-off
Fixed incorrect colour
2023-12-06 20:39:37 +01:00
PeekabooSteam
0e78b7559b Robots are no longer considered for waypoints 2023-12-06 15:27:05 +00:00
PeekabooSteam
25edfc45e5 Added coalition visibility tooltips 2023-12-06 15:03:15 +00:00
PeekabooSteam
885825e5cc Fixed incorrect colour 2023-12-06 14:54:36 +00:00
Pax1601
344413ae74 Undone wrong change in pcall 2023-12-06 13:08:52 +01:00
Pax1601
fa0643987b Remove need for path variable 2023-12-06 12:37:59 +01:00
Pax1601
dcff462b32 v0.4.11-alpha-rc3 2023-12-06 09:15:44 +01:00
Pax1601
fa04e5f8bb Merge pull request #670 from Pax1601/650-robots-can-be-sent-to-refuel-while-protected
Added extra protection for robots
2023-12-06 08:17:21 +01:00
Pax1601
c8d5f9ce0e Formatted file 2023-12-06 08:17:01 +01:00
Pax1601
55642a89b1 Merge pull request #671 from Pax1601/651-control-tips-quick-options-shown-but-nothing-happens
Removed Quick Options option
2023-12-06 08:12:00 +01:00
PeekabooSteam
f305aa3929 Removed Quick Options option 2023-12-05 21:51:32 +00:00
PeekabooSteam
47ee88c339 Added extra protection for robots 2023-12-05 20:44:26 +00:00
Pax1601
022e041f68 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-05 19:30:50 +01:00
Pax1601
0cc53890c1 v0.4.10-alpha-rc2 2023-12-05 19:30:34 +01:00
Pax1601
e37f7a4977 v0.4.10-alpha-rc1 2023-12-05 19:18:37 +01:00
Pax1601
8d03c6a767 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-05 15:59:25 +01:00
Pax1601
e29fdfd8c7 Fixed typo in map attribution 2023-12-05 15:59:19 +01:00
Pax1601
af619c3687 Merge pull request #666 from Pax1601/rc1-fixes
Rc1 fixes
2023-12-05 15:44:29 +01:00
Pax1601
6afb6682ea Fixed IADS creation, no longer clogs the server 2023-12-05 15:43:48 +01:00
Pax1601
9c2c7f45c6 Demo mode disabled 2023-12-05 11:35:10 +01:00
Pax1601
7fbc19e90a Merge pull request #665 from Pax1601/rc1-fixes
RC1 fixes
2023-12-05 11:31:14 +01:00
Pax1601
8f2f73dc0e RC1 fixes 2023-12-05 11:26:18 +01:00
Pax1601
24a1681337 Merge pull request #663 from Pax1601/task-optimization
Task optimization
2023-12-05 10:07:09 +01:00
Pax1601
304e8ba3a0 Fixed compilation warnings 2023-12-05 10:06:47 +01:00
Pax1601
45b840fa72 Changed default multiplier value 2023-12-05 09:24:13 +01:00
Pax1601
82704f042b Added check on negative speed 2023-12-05 09:22:22 +01:00
Pax1601
87d71da55e Small tweak to multiplier 2023-12-05 09:14:06 +01:00
Pax1601
71cf7c67f7 Fixed change altitude and speed for helicopters 2023-12-05 09:11:36 +01:00
Pax1601
62142ed976 Version 2 of tasking optimization 2023-12-04 21:06:13 +01:00
Pax1601
f56bd514dc Fixed tab order in installer 2023-12-03 21:30:16 +01:00
Pax1601
e30f161d1d Removed unnecessary file 2023-12-03 21:11:14 +01:00
Pax1601
720bfb3118 Added git clean command 2023-12-03 21:06:05 +01:00
Pax1601
4100a3cc67 v0.4.9-alpha-rc1 2023-12-03 21:04:19 +01:00
Pax1601
942993ff6d Added ranges for SAM Sites 2023-12-03 21:00:32 +01:00
Pax1601
fbf435c799 Added missing images, changed mop to da aaa 2023-12-03 20:46:26 +01:00
Pax1601
8fdb0d82e8 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-03 19:54:36 +01:00
Pax1601
dcbebab61b Updated databases 2023-12-03 19:54:33 +01:00
Pax1601
7b10afae43 Merge pull request #644 from Pax1601/639-create-boilerplate-plugin
Added boilerplate plugin
2023-12-03 19:51:32 +01:00
PeekabooSteam
81d8a88abd Removed old definition file 2023-12-03 18:48:51 +00:00
Pax1601
cb14158a0f Merge pull request #645 from WoodyXP/main
Example script to set airbase to a certain coalition
2023-12-03 19:32:13 +01:00
PeekabooSteam
38fc60352a Fixed typo 2023-12-03 18:12:18 +00:00
PeekabooSteam
3748f0d6e3 Added extensive documentation. 2023-12-03 14:23:08 +00:00
Stefan Arsic
edd626d5e5 Example script to set airbase to a certain coalition 2023-12-03 14:38:58 +01:00
PeekabooSteam
f785e75686 Corrected package name 2023-12-03 12:28:19 +00:00
PeekabooSteam
9a46ed70b7 Added boilerplate plugin 2023-12-03 12:24:52 +00:00
Pax1601
532c09a815 Fixed merge error 2023-12-03 11:49:39 +01:00
Pax1601
e430d38c63 Merge pull request #643 from Pax1601/525-ships-spawn-with-0-health-indicated
Health correctly computed for ships too
2023-12-03 11:35:55 +01:00
Pax1601
289b36de6d Health correctly computed for ships too 2023-12-03 11:35:37 +01:00
Pax1601
7e01f40e5c Merge pull request #642 from Pax1601/537-cannot-copy-paste-robots
It's now possible to copy robots
2023-12-03 11:10:17 +01:00
Pax1601
cac4bb5f13 It's now possible to copy robots
Know limitation: it's not possible to copy payloads of units spawned by other scripts. They must be in the .miz file. Don't think we can do much about this.
2023-12-03 11:09:50 +01:00
Pax1601
c8bb041887 Merge pull request #635 from Pax1601/633-unable-to-hide-olympus-controlled-units
633 unable to hide olympus controlled units
2023-12-02 18:32:40 +01:00
PeekabooSteam
9302c5c6d1 Merge branch '633-unable-to-hide-olympus-controlled-units' of https://github.com/Pax1601/DCSOlympus into 633-unable-to-hide-olympus-controlled-units 2023-12-02 16:05:51 +00:00
PeekabooSteam
84a3313f2c TS declarations 2023-12-02 16:04:12 +00:00
PeekabooSteam
1eb3beeb2e Merge branch 'main' into 633-unable-to-hide-olympus-controlled-units 2023-12-02 15:58:37 +00:00
PeekabooSteam
d0e6ef8c6c Changed order 2023-12-02 12:57:58 +00:00
PeekabooSteam
5da1df7e20 Added Olympus unit toggle 2023-12-02 12:47:00 +00:00
Pax1601
16fa6d9805 Updated databases 2023-12-02 13:25:46 +01:00
Pax1601
0ca7766689 Merge pull request #634 from Pax1601/minor-refactoring
Minor refactoring
2023-12-02 12:37:55 +01:00
Pax1601
4342575418 Merge pull request #632 from Pax1601/631-alignment-of-second-bar-in-visibility-options-is-too-tall
Fixed bar height
2023-12-02 12:37:41 +01:00
Pax1601
4cdb73a60d Fixed error in address for configuration 2023-12-02 12:36:42 +01:00
PeekabooSteam
a23c53bcb8 Fixed bar height 2023-12-02 11:04:37 +00:00
Pax1601
19ac4f92e0 Merge branch 'main' into minor-refactoring 2023-12-02 11:20:38 +01:00
Pax1601
0b8f48b4fd Merge pull request #615 from Pax1601/602-attack-mode-not-working-on-ground-and-navy-units
Added ATTACK state for ground and navy units
2023-12-02 11:19:05 +01:00
Pax1601
d2fa94a6cb Minor graphical tweak 2023-12-02 11:17:30 +01:00
Pax1601
da1c674911 Merge branch 'main' into 602-attack-mode-not-working-on-ground-and-navy-units 2023-12-02 10:53:24 +01:00
Pax1601
7184bc1eb2 Merge branch 'main' into 602-attack-mode-not-working-on-ground-and-navy-units 2023-12-02 10:49:28 +01:00
Pax1601
37f30a0f1a Merge pull request #629 from Pax1601/Shredmetal-patch-1
Update LEGAL
2023-12-02 10:48:43 +01:00
Pax1601
04f4b3e78a Merge pull request #626 from Pax1601/609-update-top-menu-ui
Styled top bar, fixed IADS toggle.
2023-12-02 10:48:12 +01:00
Pax1601
dbdc162fae Merge pull request #630 from Pax1601/read-config-location-with-lfs.writedir()
Read config location with lfs.writedir()
2023-12-02 10:47:33 +01:00
Pax1601
563f673fb3 Minor tweak 2023-12-02 10:46:59 +01:00
Pax1601
423e799a82 Completed reading from current instance 2023-12-02 10:40:03 +01:00
Shredmetal
4734b89414 Update LEGAL
Amended unilateral modification term to state explicitly that parties agree to be bound by such terms as modified from time to time
2023-12-02 14:33:27 +08:00
Shredmetal
6f708e7733 update LEGAL
added unilateral modification term so we can change the agreement at will without informing users beyond updating the repo
2023-12-02 14:21:38 +08:00
PeekabooSteam
f0c3f95189 Merge and fix conflict 2023-12-01 16:55:14 +00:00
Pax1601
93ca0e3f22 Added read from lfs 2023-12-01 17:44:03 +01:00
PeekabooSteam
d94432636f Styled top bar, fixed IADS toggle. 2023-12-01 15:51:02 +00:00
Pax1601
60fca35d80 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-12-01 14:12:50 +01:00
Pax1601
db71462d1c Update sample.png 2023-12-01 14:12:10 +01:00
Pax1601
86f522176a Update README.md 2023-12-01 14:08:41 +01:00
Pax1601
94ee71c48f A couple of comments 2023-12-01 13:02:18 +01:00
Pax1601
fda0b21fb0 Minor refactoring 2023-12-01 13:00:02 +01:00
Pax1601
775148cec8 Merge pull request #621 from Pax1601/610-update-spawn-menu-ui
Unit spawn menu restyled
2023-11-30 17:29:30 +01:00
Pax1601
f2dc4a1a00 Unit spawn menu restyled 2023-11-30 17:29:11 +01:00
Pax1601
eda5723a3c Merge pull request #620 from Pax1601/617-check-iads-respects-requested-units-and-add-unit-preview-on-spawn
617 check iads respects requested units and add unit preview on spawn
2023-11-30 15:55:36 +01:00
Pax1601
b044d9a6c0 Minor comments 2023-11-30 15:46:48 +01:00
Pax1601
125d5396b9 Fixed IADS creation
It now also considers airbases when creating the IADS. Fixed styling and unit types. Currently SAM Sites ranges are incorrect but will be fixed when database is updated
2023-11-30 15:36:31 +01:00
Pax1601
17b8b35a43 Added ATTACK state for ground and navy units 2023-11-30 13:08:43 +01:00
Pax1601
4bd017e3c7 Merge pull request #612 from Pax1601/542-spawn-menu-dropdowns-overlap-menu
Alignment fixed, spelling corrected
2023-11-30 11:12:52 +01:00
Pax1601
37447a7fd3 Merge pull request #613 from Pax1601/592-detect-if-installing-olympus-again-and-dont-prompt-to-set-olympusjson-properties
592 detect if installing olympus again and dont prompt to set olympusjson properties
2023-11-30 11:09:34 +01:00
Pax1601
1ed1dec65e Added full stop for Peekaboo 2023-11-30 11:08:48 +01:00
Pax1601
5e2e465813 Installer updated to allow preservation of old config 2023-11-30 11:01:45 +01:00
PeekabooSteam
335655406e Alignment fixed, spelling corrected 2023-11-30 09:41:43 +00:00
Pax1601
bf12d6330c Merge pull request #606 from Pax1601/566-ground-and-naval-units-have-roe-only-designated-option
Added a warning message for ground and navy units ROE
2023-11-29 12:57:41 +01:00
Pax1601
3cca3187ad Added a warning message for ground and navy units ROE 2023-11-29 12:57:17 +01:00
Pax1601
f4388a2cff Merge pull request #605 from Pax1601/594-bounds-for-normandy-map-are-missing
Bounds added for Normandy theatre
2023-11-29 11:54:33 +01:00
Pax1601
7cf5d324eb Bounds added for Normandy theatre 2023-11-29 11:54:16 +01:00
Pax1601
ec9ef2b0fb Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-11-29 11:06:34 +01:00
Pax1601
6c852d93a9 Minor tweak on splash screen when screen is very small 2023-11-29 11:06:31 +01:00
Pax1601
290067932e Merge pull request #604 from Pax1601/596-add-a-way-for-users-to-know-there-is-a-new-version-available
Added latest version number
2023-11-29 10:49:04 +01:00
Pax1601
4aa3a43604 Added latest version number
It pulses if a newer version is available
2023-11-29 10:46:43 +01:00
Pax1601
3c33696452 Create version.json
Added version file
2023-11-29 09:58:16 +01:00
Pax1601
3ea1ab8f30 Added link to wiki 2023-11-28 17:36:55 +01:00
Pax1601
76801f773d Merge pull request #601 from Pax1601/412-improve-importexport
412 improve importexport
2023-11-28 17:31:34 +01:00
Pax1601
de7eeec94a Completed import/export page 2023-11-28 17:30:59 +01:00
Pax1601
0723a3ab95 Merge branch 'main' into 412-improve-importexport 2023-11-28 17:15:41 +01:00
Pax1601
8ef48ad977 Implemented filename selector 2023-11-28 16:59:23 +01:00
Pax1601
ed24d1af60 Merge pull request #600 from Pax1601/fix-aim-errors
Fixed error in lead calculation code
2023-11-28 16:42:45 +01:00
Pax1601
e3dffb8245 Fixed error in lead calculation code 2023-11-28 16:41:43 +01:00
Pax1601
74310a5ad3 Fixed installation prompt about passwords 2023-11-27 21:26:48 +01:00
Pax1601
a2223165e8 Merge branch 'main' into 412-improve-importexport 2023-11-26 21:13:24 +01:00
Pax1601
a879761dc2 Installation fixes 2023-11-24 21:38:55 +01:00
Pax1601
124b909aa4 v0.4.8 2023-11-24 19:43:24 +01:00
Pax1601
858e9eb066 Merge pull request #591 from Pax1601/584-add-state-icon-for-scenic-aaa-functions
Added state icons for scenic functions
2023-11-24 17:53:02 +01:00
Pax1601
7415e0cb97 Added state icons for scenic functions
And fixed dropdowns in case of duplicate labels
2023-11-24 17:52:48 +01:00
Pax1601
915020ddc3 Merge pull request #590 from Pax1601/532-stop-any-previous-connection-requests-before-connecting-again
Added code to clear any previous connection attempt
2023-11-24 11:50:32 +01:00
Pax1601
95915489b2 Added code to clear any previous connection attempt 2023-11-24 11:49:09 +01:00
Pax1601
3e39c3351a Merge pull request #589 from Pax1601/520-south-atlantic-initial-viewpoint
Added bounds for South Atlantic map
2023-11-24 11:43:41 +01:00
Pax1601
244d32e7d2 Added bounds for South Atlantic map 2023-11-24 11:43:26 +01:00
Pax1601
16a79827b7 Merge pull request #588 from Pax1601/586-spawn-toggle-background-missing
Fixed toggles
2023-11-24 10:05:13 +01:00
Pax1601
bd6a36e9ea Merge pull request #587 from Pax1601/487-improve-simulated-firefights
Added indirect fire mode
2023-11-23 23:45:20 +01:00
Pax1601
771695af59 Added indirect fire mode 2023-11-23 23:45:00 +01:00
PeekabooSteam
e811c7bd46 Fixed toggles 2023-11-23 22:44:24 +00:00
Pax1601
20f99c287f Minor change in unit label dropdown
It now expands to fill the space, but it still overflows with long unit names as per #542
2023-11-23 20:32:42 +01:00
Pax1601
f464c9ae76 Merge pull request #585 from Pax1601/511-jf-17-isnt-assigned-to-any-roles-other-than-cap
Added JF-17 loadouts
2023-11-23 20:12:27 +01:00
Pax1601
15ccb3dc04 Added JF-17 loadouts 2023-11-23 20:11:54 +01:00
Pax1601
defe40d48f Merge pull request #583 from Pax1601/miss-on-purpose-tweaks
Added effect of acquisition range to wake units up
2023-11-23 20:09:43 +01:00
Pax1601
0f2622e821 Merge pull request #560 from Pax1601/524-units-will-not-perform-scenic-aaa-until-the-operate-as-toggle-is-toggled
Fixed missing reset of expected value of operateAs toggle
2023-11-23 20:09:09 +01:00
Pax1601
b442d238cd Fixed error in getUnitsVariable function 2023-11-23 20:08:37 +01:00
Pax1601
00f2a3c19d Merge branch 'main' into 524-units-will-not-perform-scenic-aaa-until-the-operate-as-toggle-is-toggled 2023-11-23 19:57:09 +01:00
Pax1601
dcbfdf8666 Added effect of acquisition range to wake units up
Note: alertness time constant suppressed
2023-11-23 16:40:18 +01:00
Pax1601
6e84423032 Merge pull request #577 from Pax1601/576-toggles-gone-walkabout
Fixed UCP toggles, added copy-paste control for plugins
2023-11-23 10:29:23 +01:00
PeekabooSteam
912ab75a96 Moved Database Manager Link 2023-11-22 17:55:39 +00:00
PeekabooSteam
1022fc2f0c Fixed UCP toggles, added copy-paste control for plugins 2023-11-22 17:15:23 +00:00
Pax1601
65edce855b Merge pull request #568 from Pax1601/loading-screen
Loading screen
2023-11-22 15:13:11 +01:00
Pax1601
0ba05d5795 Merge pull request #572 from Pax1601/540-grouped-units-cant-be-selected
Grouped units can be deleted now
2023-11-22 15:13:02 +01:00
Pax1601
1b17e17290 Added some TODO comments
And very minor refactoring
2023-11-22 15:12:28 +01:00
Pax1601
87957df1fb Fixed incorrect behaviour when rotating unit destinations
And a minor map code refactoring
2023-11-22 15:04:09 +01:00
Pax1601
d3f8d4eff7 Grouped units can be deleted now
Also added some performance optimizations on drawing of selected units and removed destination preview icon for single unit selection
2023-11-22 13:12:35 +01:00
Pax1601
3ffeed3b39 Merge pull request #569 from Pax1601/533-allow-users-to-edit-the-config-json-during-the-installation-process
533 allow users to edit the config json during the installation process
2023-11-22 11:35:06 +01:00
Pax1601
4197e4402c Relative paths for nwjs and node folders 2023-11-22 11:33:13 +01:00
Pax1601
1cfe6f5583 Added simple loading screen 2023-11-22 11:32:13 +01:00
Pax1601
ad5cb83abf Completed server version 2023-11-21 17:35:09 +01:00
Pax1601
f4a4882dbc Merge pull request #564 from Pax1601/563-map-icon-disappears-after-changing-map-type
We no longer LOSE the icon
2023-11-21 14:38:34 +01:00
Pax1601
ecb2cf182a Merge pull request #561 from Pax1601/Shredmetal-patch-1
Update LEGAL
2023-11-21 14:38:20 +01:00
Pax1601
6aea839e04 Added configurator GUI 2023-11-21 14:34:51 +01:00
PeekabooSteam
e20d2fa95a We no longer LOSE the icon 2023-11-20 20:33:41 +00:00
Pax1601
806d0cc52f Added ability for users to edit configuration during installation 2023-11-20 18:19:41 +01:00
Shredmetal
2a2baaf324 Update LEGAL 2023-11-21 01:02:03 +08:00
Pax1601
74989ec015 Fixed missing reset of expected value of operateAs toggle 2023-11-20 12:30:44 +01:00
Pax1601
31af3a53ce Merge pull request #559 from Pax1601/528-unknown-units-have-no-icons
Added default marker for unkown units
2023-11-20 11:43:42 +01:00
Pax1601
361d51b55d Merge pull request #545 from Pax1601/531-november-ui-cleanup
531 november UI cleanup
2023-11-20 09:45:36 +01:00
Pax1601
a12c09eba5 Minor refactoring 2023-11-20 09:44:59 +01:00
Pax1601
bcfe0653bd Merge pull request #544 from Pax1601/543-duplicated-categories-due-to-misspelling
Fixed typos
2023-11-20 09:35:10 +01:00
PeekabooSteam
c43bc763f3 Fixed typos 2023-11-19 13:47:24 +00:00
PeekabooSteam
85325c17ac More styling, added pulse to scenic actions from (?) 2023-11-19 11:17:00 +00:00
PeekabooSteam
178706f8de Finalised styling for UCP 2023-11-18 22:02:59 +00:00
Pax1601
51defbb8b2 Added default marker for unkown units 2023-11-18 19:01:47 +01:00
PeekabooSteam
84cf9aa27a More changes from the list 2023-11-17 22:44:15 +00:00
PeekabooSteam
a66098e080 Merge branch 'main' into 531-november-ui-cleanup 2023-11-17 21:46:58 +00:00
Pax1601
283b9e682e v0.4.7 2023-11-17 22:04:21 +01:00
Pax1601
8b5956e76b Merge pull request #536 from Pax1601/489-show-all-the-action-options-of-the-selected-units-even-if-some-units-dont-have-them
489 show all the action options of the selected units even if some units dont have them
2023-11-17 22:02:51 +01:00
Pax1601
017a89b945 getDesc().category reimplemented
unit:getCategory() reports "Airplane" for Helicopters
2023-11-17 22:02:32 +01:00
Pax1601
5bc685182b Merge branch 'main' into 489-show-all-the-action-options-of-the-selected-units-even-if-some-units-dont-have-them 2023-11-17 21:40:09 +01:00
Pax1601
f47fc2fb19 Merge pull request #535 from Pax1601/534-olympus-not-sending-data-with-dcs-open-beta-29148111
Changed unit:getCategory to Object.getCategory(unit)
2023-11-17 21:35:20 +01:00
Pax1601
11d6f25606 Changed unit:getCategory to Object.getCategory(unit)
And added some isExist guards
2023-11-17 21:34:50 +01:00
Pax1601
331692e3d3 Merge branch '489-show-all-the-action-options-of-the-selected-units-even-if-some-units-dont-have-them' of https://github.com/Pax1601/DCSOlympus into 489-show-all-the-action-options-of-the-selected-units-even-if-some-units-dont-have-them 2023-11-17 21:10:49 +01:00
Pax1601
7483225e0d Small tweak to login page 2023-11-17 21:10:46 +01:00
PeekabooSteam
f00df5ca3f Some changes done 2023-11-17 17:07:56 +00:00
Pax1601
22ae882032 Unit gets forcefully deselected when hidden 2023-11-17 17:45:10 +01:00
Pax1601
fbab82e4de Merge branch 'main' into 489-show-all-the-action-options-of-the-selected-units-even-if-some-units-dont-have-them 2023-11-17 17:26:56 +01:00
Pax1601
ca81d1c4ce Merge pull request #530 from Pax1601/529-add-favicon
Favicons
2023-11-17 17:24:03 +01:00
Pax1601
a1884ab19f Merge pull request #527 from Pax1601/522-flashpulse-robot-lock-when-trying-to-give-orders-to-protected-units
Lock flashes on protected robot interaction
2023-11-17 17:23:18 +01:00
Pax1601
8905cd5e85 Merge pull request #526 from Pax1601/523-selected-units-dont-get-hidden
Selected units now hidden on request
2023-11-17 17:22:36 +01:00
PeekabooSteam
8d5ed33ad8 Favicons 2023-11-17 11:35:55 +00:00
Pax1601
b747752b76 Fixed error in follow command 2023-11-17 07:59:04 +01:00
PeekabooSteam
4e13daa270 Lock flashes on protected robot interaction 2023-11-16 23:08:01 +00:00
PeekabooSteam
c00096bd9a Selected units now hidden on request 2023-11-16 22:26:09 +00:00
PeekabooSteam
210c1fbecf Added a selective interface for import and export 2023-11-16 21:44:40 +00:00
Pax1601
4a54011aac Large rework of context menus for units and map 2023-11-16 15:31:07 +01:00
PeekabooSteam
b89c5142b6 Merge and fix 2023-11-16 11:28:32 +00:00
PeekabooSteam
0421f6b8fe Fixed regex undefined 2023-11-16 11:16:54 +00:00
Pax1601
0c50141be6 v0.4.6 2023-11-15 16:42:24 +01:00
Pax1601
a71b8806e7 Update groundunitdatabase.json 2023-11-15 16:06:52 +01:00
Pax1601
e0a27c574f Merge pull request #519 from Pax1601/493-for-ground-units-add-marker-symbol-in-database
493 for ground units add marker symbol in database
2023-11-15 15:38:59 +01:00
Pax1601
8d7a49a31f Created group handlers 2023-11-15 15:38:16 +01:00
Pax1601
25e2c50438 Added unit marker to database and implemented better grouping 2023-11-14 17:43:24 +01:00
Pax1601
e3423ea9a3 Merged new databases 2023-11-14 07:53:01 +01:00
Pax1601
812112858c Merge branch 'main' into 493-for-ground-units-add-marker-symbol-in-database 2023-11-13 19:27:41 +01:00
Pax1601
8db1357904 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-11-13 18:55:19 +01:00
Pax1601
bba0aa9f52 Fixed databasemanager overflow 2023-11-13 18:54:11 +01:00
Pax1601
1cc549b24a Added entry to databases 2023-11-13 18:02:08 +01:00
Pax1601
7cafeb73ca Added tags to unit spawn menu 2023-11-13 16:04:53 +01:00
Pax1601
772f082913 Tweaked installer message 2023-11-13 09:08:40 +01:00
Pax1601
9f7efe3018 Merge pull request #517 from Pax1601/437-f-14b-not-spawning-with-weapons
Fixed errors in loadouts scripts
2023-11-12 18:44:18 +01:00
Pax1601
a28584b08b Fixed errors in loadouts scripts 2023-11-12 18:43:49 +01:00
Pax1601
5cba46a482 Merge pull request #516 from Pax1601/437-f-14b-not-spawning-with-weapons
Fixed loadout generator adding exceptions for Tomcats
2023-11-12 17:43:37 +01:00
Pax1601
a15b7620eb Fixed loadout generator adding exceptions for Tomcats 2023-11-12 17:42:54 +01:00
PeekabooSteam
9ef6efa3e0 Mid-way commit 2023-11-12 16:18:31 +00:00
Pax1601
49bff88c4e Radio and TACAN frequencies are now clamped 2023-11-12 17:18:18 +01:00
Pax1601
80af34fa3e Merge pull request #515 from Pax1601/265-cloning-a-dead-unit-fails
Dead units can now be cloned
2023-11-12 16:36:04 +01:00
Pax1601
1d6f2644aa Dead units can now be cloned 2023-11-12 16:35:31 +01:00
Pax1601
dc61d364d1 Merge pull request #514 from Pax1601/448-on-chrome-fps-drops-to-single-digits-when-zoomed-in
Implemented custom fast renderer for range circles
2023-11-12 15:50:44 +01:00
Pax1601
78de9dd538 Implemented custom fast renderer for range circles
It's a bit hacky since I had to override a default leaflet renderer function. Works well but may be injected in a more elegant way.
2023-11-12 15:49:46 +01:00
Pax1601
ccaea5b9d1 Better unit explosion buttons design 2023-11-12 14:08:10 +01:00
Pax1601
e02e9de55d Updated databases 2023-11-09 19:27:32 +01:00
Pax1601
40da192dbb Merge pull request #512 from Pax1601/486-add-more-advanced-effects
486 add more advanced effects
2023-11-09 08:27:06 +01:00
Pax1601
c8254238c7 Scrollable unit control panel tweak 2023-11-09 08:26:43 +01:00
Pax1601
9caee0c77c Implemented buttons to apply advanced controls directly to units 2023-11-08 23:33:27 +01:00
Pax1601
b9830f0190 Merge branch 'main' into 486-add-more-advanced-effects 2023-11-08 22:04:52 +01:00
Pax1601
02a0a9b783 Merge pull request #504 from Pax1601/484-add-life-meter-to-ground-units
484 add life meter to ground units
2023-11-08 21:57:27 +01:00
Pax1601
ea1758a1a9 Added backend code for health display
And fixed the issue of ground units not being deleted correctly
2023-11-08 21:56:39 +01:00
PeekabooSteam
b43afd4e9c Export customisation working - but ugly. 2023-11-08 14:09:35 +00:00
PeekabooSteam
7700aa2030 Merge branch 'main' into 412-improve-importexport 2023-11-08 12:52:27 +00:00
Pax1601
d5d8391f63 Merge pull request #508 from Pax1601/494-make-the-installer-more-clear-specify-that-olympus-must-be-installed-in-savedgames
Changed message and fixed wrong installation folder after user selection
2023-11-08 10:17:40 +01:00
Pax1601
b508d2301b Changed message and fixed wrong installation folder after user selection 2023-11-08 10:16:33 +01:00
Pax1601
01b3336709 Merge pull request #507 from Pax1601/495-make-ui-port-configurable-from-olympusjson
Added port selection to config
2023-11-08 09:59:50 +01:00
Pax1601
6ba37aefd6 Added port selection to config 2023-11-08 09:59:21 +01:00
PeekabooSteam
e68683acb7 Export matrix reads from data 2023-11-07 22:04:09 +00:00
Pax1601
a804904ff5 Merge pull request #506 from Pax1601/dynamic-resizing
Dynamic resizing
2023-11-07 19:36:08 +01:00
Pax1601
eacb89176c Completed new resizable design 2023-11-07 17:37:19 +01:00
PeekabooSteam
ec971aa822 Merge branch 'main' into 484-add-life-meter-to-ground-units 2023-11-06 22:29:23 +00:00
PeekabooSteam
e1f404c647 Added some doc comments 2023-11-06 22:28:44 +00:00
PeekabooSteam
5f1e32d610 Conflict fix 2023-11-06 21:51:45 +00:00
PeekabooSteam
732ee2bbb9 Added + for naval and ground units 2023-11-06 21:49:54 +00:00
Pax1601
1e461250d5 Added advanced effects 2023-11-06 19:26:15 +01:00
Pax1601
f727174044 Testing of dynamic resizing 2023-11-06 18:30:59 +01:00
Pax1601
7edc687f7b Merge pull request #501 from Pax1601/499-spawn-menu-reorganisation
Air defence has its own spawn icon
2023-11-06 11:13:12 +01:00
Pax1601
596fbf0b87 Merge branch 'main' into 499-spawn-menu-reorganisation 2023-11-06 11:12:46 +01:00
PeekabooSteam
8dc48c10c3 Added dialog 2023-11-05 22:35:00 +00:00
PeekabooSteam
5db90e5896 Changed air defence form to extend ground units' form 2023-11-05 19:24:23 +00:00
PeekabooSteam
dd811def07 Added health bar 2023-11-05 19:11:42 +00:00
Pax1601
5273291e9a Merge pull request #503 from Pax1601/485-improve-miss-on-purpose
485 improve miss on purpose
2023-11-05 17:35:03 +01:00
Pax1601
130dbda499 Merge branch 'main' into 485-improve-miss-on-purpose 2023-11-05 17:34:56 +01:00
Pax1601
769aea7e4e Merge pull request #502 from Pax1601/500-log-in-form-needs-to-submit-when-pressing-enterreturn
500 log in form needs to submit when pressing enterreturn
2023-11-05 17:28:42 +01:00
Pax1601
fa3d65bde6 Completed miss on purpose functionality 2023-11-05 17:26:39 +01:00
PeekabooSteam
073281135c Fixed odd 'undefined' bug 2023-11-05 13:15:41 +00:00
PeekabooSteam
4c7f979e56 Merge branch '498-set-ucp-and-uip-toggles-into-olympus-context' into 500-log-in-form-needs-to-submit-when-pressing-enterreturn 2023-11-05 13:08:24 +00:00
PeekabooSteam
a5bfb4f8d2 Form submits on return press 2023-11-05 13:05:46 +00:00
PeekabooSteam
a04780f311 Merge branch 'main' into 500-log-in-form-needs-to-submit-when-pressing-enterreturn 2023-11-05 12:37:36 +00:00
PeekabooSteam
aad0fd22ad Air defence has its own spawn icon 2023-11-05 10:57:53 +00:00
Pax1601
bc1c3994d3 Merge branch 'main' into 485-improve-miss-on-purpose 2023-11-04 10:21:37 +01:00
Pax1601
840033aa6a Merge pull request #496 from Pax1601/468-robot-protection-toggle
468 robot protection toggle
2023-11-04 10:10:09 +01:00
Pax1601
9cc6e9e790 More work on miss on purpose 2023-11-04 09:57:18 +01:00
PeekabooSteam
b1ad2f409e Controlling panels and spawn menu from context 2023-11-03 22:36:35 +00:00
PeekabooSteam
7106646042 Updated landAtPoint logic 2023-11-03 18:28:05 +00:00
PeekabooSteam
31405119f0 Enabled mixed-group actions, fixed some helicopter messages. 2023-11-03 18:17:40 +00:00
PeekabooSteam
2e5ee93361 Tweaked colours. 2023-11-03 14:05:39 +00:00
PeekabooSteam
f981a661d5 Added lock image and tooltip/titles. 2023-11-03 13:29:09 +00:00
Pax1601
7e05bbf5e3 Improved scheduler logging 2023-11-03 11:37:09 +01:00
PeekabooSteam
4465f4a3bb PoC of robot protection 2023-11-02 23:03:17 +00:00
PeekabooSteam
ade4f183cd Commit so I can switch to another branch. 2023-11-02 18:22:42 +00:00
Pax1601
99dc61799f Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-11-02 17:24:39 +01:00
Pax1601
a213b94606 Minor fixes 2023-11-02 17:24:35 +01:00
Pax1601
6600ed8cbb Merge pull request #473 from Pax1601/357-map-context-switching
357 map context switching
2023-11-02 09:46:09 +01:00
PeekabooSteam
826bf12bd6 Merge branch 'main' into 357-map-context-switching 2023-10-31 20:30:18 +00:00
Pax1601
528e0db79c Updated demo.js 2023-10-31 17:48:09 +01:00
Pax1601
11a5fec195 Added effect of vertical velocity and of scatter and intensity 2023-10-30 15:56:10 +01:00
Pax1601
c0f3f3a40a Added scatter and intensity selectors in UI 2023-10-30 12:46:49 +01:00
Pax1601
88844db23a Added shots scatter and intensity variables to backend 2023-10-30 10:09:49 +01:00
Pax1601
31710b4e28 Updated legal text 2023-10-30 09:56:07 +01:00
Pax1601
42d2f6400b Merge pull request #476 from Pax1601/edits_legal
Update and rename COPYING to LEGAL
2023-10-28 14:42:03 +02:00
Pax1601
2701d6adc0 Merge pull request #472 from Pax1601/464-proposed-hot-group-behaviour-tweak-to-be-like-lakecraft-shift-+-1-appends-to-group
464 proposed hot group behaviour tweak to be like lakecraft shift + 1 appends to group
2023-10-28 14:40:06 +02:00
Pax1601
5a4b203937 Merge pull request #477 from Pax1601/463-delete-needs-three-buttons
Added new delete method dialog
2023-10-28 14:38:42 +02:00
Pax1601
74cb7877cb Merge pull request #474 from Pax1601/460-sam-threat-rings-appear-when-they-shouldnt
460 sam threat rings appear when they shouldnt
2023-10-28 14:36:24 +02:00
PeekabooSteam
f954338c27 Added new delete method dialog 2023-10-27 17:26:41 +01:00
Shredmetal
cc729b1d25 Update and rename COPYING to LEGAL
Cleaned up the legal text
2023-10-26 16:45:58 +08:00
PeekabooSteam
4a4b1d6b00 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus into main 2023-10-20 11:04:24 +01:00
Pax1601
d14741f3b1 Merge pull request #471 from Pax1601/470-spawn-menu-qty-sorted-alphabetically-not-numerically
Unit spawn qty now sorted numerically.
2023-10-19 01:29:45 +02:00
PeekabooSteam
94684fff9f More spacing tweaking 2023-10-18 13:54:33 +01:00
PeekabooSteam
44deef4a5a Tweaked spacing 2023-10-18 13:23:25 +01:00
PeekabooSteam
67079e1c0b Munitions constrained to a scrollable 2023-10-18 13:20:54 +01:00
PeekabooSteam
005ffc55ce var => let 2023-10-18 12:15:59 +01:00
PeekabooSteam
1691b0b30c Range rings only showing when necessary 2023-10-18 12:13:51 +01:00
PeekabooSteam
e4e55430ca Optimised quantity option generator 2023-10-18 11:17:05 +01:00
PeekabooSteam
4d31d9d748 Unit spawn qty now sorted numerically. 2023-10-18 10:23:50 +01:00
PeekabooSteam
1413f596fb Improved filter logic 2023-10-17 11:27:21 +01:00
PeekabooSteam
c0aee94da5 Hotgroup logic updated 2023-10-16 19:45:51 +01:00
PeekabooSteam
8e545346e6 Exploratory tweaks 2023-10-16 09:13:44 +01:00
PeekabooSteam
2b1272c70d Removed needless [] 2023-10-15 11:53:12 +01:00
PeekabooSteam
121f9b6ec3 Tweaked string functions 2023-10-15 11:51:49 +01:00
PeekabooSteam
6f9722143e Took shift and alt requirements from T key for demo data 2023-10-15 10:59:39 +01:00
PeekabooSteam
5bf62f4b93 Removed needless context.ts ref 2023-10-15 10:24:41 +01:00
PeekabooSteam
79319dd006 Shortcuts can be set to a context 2023-10-15 10:22:03 +01:00
PeekabooSteam
fdcff53697 Shortcuts now settable to a context. 2023-10-15 09:43:26 +01:00
Pax1601
24cd2729db Startup script updated 2023-10-15 09:54:57 +02:00
Pax1601
9ca2703f16 More package build updates 2023-10-14 12:32:24 +02:00
Pax1601
1a579c5755 Build scripts updated 2023-10-14 12:13:32 +02:00
Pax1601
7344c761fe Small bugfixes 2023-10-14 11:07:39 +02:00
Pax1601
203a981fed Merge pull request #459 from Pax1601/small-issues
Modified isTanker and isAWACS to isActiveTanker and isActiveAWACS
2023-10-13 16:35:52 +02:00
Pax1601
d3faf65900 Modified isTanker and isAWACS to isActiveTanker and isActiveAWACS 2023-10-13 16:35:11 +02:00
Pax1601
5efbf81090 Merge pull request #458 from Pax1601/small-issues
Fixed wrong cursor type
2023-10-13 15:23:51 +02:00
Pax1601
9ffab7d531 Fixed wrong cursor type 2023-10-13 15:23:29 +02:00
Pax1601
0886ff1be1 Merge pull request #456 from Pax1601/small-issues
Removed preferCanvas option for map
2023-10-13 12:49:12 +02:00
Pax1601
2893182713 Removed preferCanvas option for map
Which apparently causes Chrome to slow down when zoomed in. More test required to check performance.
2023-10-13 12:48:51 +02:00
Pax1601
478bb18ab2 Updated version number 2023-10-11 18:05:58 +02:00
Pax1601
eae07ca6cc Merge pull request #455 from Pax1601/small-issues
Small issues
2023-10-11 18:01:46 +02:00
Pax1601
2264faabfc Updated databases 2023-10-11 18:01:27 +02:00
Pax1601
4cdf82cb14 Database fixes 2023-10-11 15:20:24 +02:00
Pax1601
5a7e511dac Merge pull request #450 from Pax1601/small-issues
Small issues
2023-10-11 12:56:04 +02:00
Pax1601
a29eb3d343 Added stop command to helicopters 2023-10-11 12:55:41 +02:00
Pax1601
3c65aefe61 Fixed destination preview handle showing incorrectly 2023-10-11 12:49:44 +02:00
Pax1601
867d7697d2 Moved tanker/AWACS button to control panel 2023-10-11 12:37:16 +02:00
Pax1601
ebee6610a3 Added tanker and off state icons 2023-10-11 08:00:43 +02:00
Pax1601
c26691c2fc Merge pull request #449 from Pax1601/small-issues
Added "land at point" state for helicopters
2023-10-10 17:11:05 +02:00
Pax1601
a038d6e999 Added "land at point" state for helicopters 2023-10-10 17:10:29 +02:00
Pax1601
aa1550ca01 Merge pull request #446 from Pax1601/small-issues
TACAN and radio can now be set on carriers
2023-10-10 15:49:15 +02:00
Pax1601
80eaa643c9 TACAN and radio can now be set on carriers 2023-10-10 15:27:42 +02:00
Pax1601
d67d9c1afd Merge pull request #445 from Pax1601/small-issues
Added Strike Eagle
2023-10-10 15:18:43 +02:00
Pax1601
af15fc123d Added Strike Eagle 2023-10-10 15:18:19 +02:00
Pax1601
0ce56e6529 Merge pull request #444 from Pax1601/metadata
Added abilities and description to spawn menu
2023-10-10 14:34:37 +02:00
Pax1601
258164c285 Added abilities and description to spawn menu 2023-10-10 14:34:19 +02:00
Pax1601
746617deb0 Merge pull request #443 from Pax1601/427-toggle-mouse-info-format-latlng-grid-decimals
Can now get LatLng, MGRS and UTM location data
2023-10-09 10:46:15 +02:00
Pax1601
c51d00673d Merge pull request #441 from Pax1601/440-refuelling-misspelled-as-refueling
Missing Ls added
2023-10-09 10:45:32 +02:00
PeekabooSteam
bedd21522a Can now get LatLng, MGRS and UTM location data 2023-10-08 16:44:55 +01:00
PeekabooSteam
382013d0ca Missing Ls added 2023-10-06 16:56:09 +01:00
Pax1601
3794207d97 Added missing button 2023-10-06 16:20:43 +02:00
Pax1601
2805323cfa Merge pull request #439 from Pax1601/small-bugfixes
Small bugfixes
2023-10-06 16:08:38 +02:00
Pax1601
0db2e56e32 Completed range rings 2023-10-06 16:07:54 +02:00
Pax1601
a33ad18322 Merge pull request #438 from Pax1601/432-display-in-game-time-and-elapsed-time
432 display in game time and elapsed time
2023-10-06 14:28:40 +02:00
PeekabooSteam
885ef6b357 Time font weight now bold 2023-10-05 17:59:09 +01:00
PeekabooSteam
2435072b07 'Connected' messaged is now a clock/timer 2023-10-05 15:12:07 +01:00
Pax1601
d462bd16b5 Implemented range rings 2023-10-05 13:51:13 +02:00
Pax1601
b08a3835dc Some database changes, started to add threat rings 2023-10-05 11:02:02 +02:00
Pax1601
ace0908d84 Merge pull request #436 from Pax1601/328-add-simple-miss-on-purpose-mode-for-aaa
328 add simple miss on purpose mode for aaa
2023-10-05 10:04:52 +02:00
Pax1601
5186fffb5e Merge commit 2023-10-05 10:04:40 +02:00
Pax1601
c5160c9baa Modified database editor 2023-10-05 10:02:23 +02:00
Pax1601
63acc94558 Merge pull request #434 from Pax1601/433-remove-scale-tool-replace-with-space-efficient-version-of-server-performance-monitor
433 remove scale tool replace with space efficient version of server performance monitor
2023-10-05 09:11:38 +02:00
PeekabooSteam
fc82407d9a Grammatical update 2023-10-04 20:55:01 +01:00
Pax1601
a0ac9eb285 Merge branch 'main' into 328-add-simple-miss-on-purpose-mode-for-aaa 2023-10-04 21:21:08 +02:00
PeekabooSteam
fc835eaba7 Remove debugger line 2023-10-04 20:11:55 +01:00
PeekabooSteam
f7b3e5bf77 Moved server performance indicators; control tips working again. 2023-10-04 20:07:49 +01:00
Pax1601
e41484186b Merge pull request #431 from Pax1601/422-coalitions-can-see-each-others-bullseye
Bullseyes now coalition-limited
2023-10-04 14:55:02 +02:00
PeekabooSteam
e0bfe6a96c Bullseyes now coalilition limited 2023-10-04 13:14:36 +01:00
Pax1601
228f184548 Merge pull request #430 from Pax1601/423-some-improvements-on-units-list
Improved visuals and truncated unit names
2023-10-04 14:11:44 +02:00
PeekabooSteam
892ce4c453 Improved visuals and truncated unit names 2023-10-03 21:57:51 +01:00
Pax1601
569d45d58a Added "operate as" toggle 2023-10-03 17:31:44 +02:00
Pax1601
ce5f00e075 Added options for miss on purpose and scenic AAA 2023-10-03 15:25:45 +02:00
Pax1601
4da407008e More work on miss on purpose 2023-10-02 21:52:04 +02:00
Pax1601
96e79cc8ae Merge pull request #429 from Pax1601/map-bugfixes
Multiple bugfixes
2023-10-02 17:30:59 +02:00
Pax1601
ee93806e19 Multiple bugfixes 2023-10-02 17:29:54 +02:00
Pax1601
fcb02602a0 Reformatted some files 2023-10-02 10:12:24 +02:00
Pax1601
5d4fdf1e76 Merge pull request #411 from Pax1601/410-update-shortcuts-to-plugin-friendly-format
Converted for plugin use
2023-10-02 09:03:30 +02:00
Pax1601
9af59fb51c Merge pull request #418 from Pax1601/417-unit-list
417 unit list
2023-10-02 09:01:28 +02:00
Pax1601
6493d37b7c Merge pull request #421 from Pax1601/419-server-is-paused
User now alerted when server is paused.
2023-10-02 08:59:48 +02:00
PeekabooSteam
a82c033da0 Timeout much shorter when server is paused to reduce update lag 2023-10-02 07:15:00 +01:00
PeekabooSteam
91484e1c98 Can now toggle unit labels with L 2023-10-01 21:42:23 +01:00
PeekabooSteam
3db5202cdf User now alerted when server is paused. 2023-10-01 20:53:30 +01:00
PeekabooSteam
5a28974027 Added additive hotgroup select 2023-10-01 20:12:36 +01:00
PeekabooSteam
4d694f1f74 Added Escape and no-tab-swap-hotgroups 2023-10-01 20:02:45 +01:00
Pax1601
5035c408e7 Basic scenic and miss on purpose AAA modes 2023-10-01 19:15:56 +02:00
Pax1601
d209f98265 Fixed wrong init of altitude sliders in spawn menu 2023-10-01 15:47:23 +02:00
PeekabooSteam
85b1404321 More sorting, changed keybind to U 2023-10-01 12:00:10 +01:00
PeekabooSteam
72c6e4e94e Using proper add and not being lazy 2023-09-30 22:33:47 +01:00
PeekabooSteam
eb46ed2768 Emitted decs 2023-09-30 22:30:29 +01:00
PeekabooSteam
7f4f01c9e8 Alpha of unit list 2023-09-30 22:19:48 +01:00
Pax1601
691d2746e6 Merge pull request #416 from Pax1601/385-setting-altitude-to-silly-number
Fixed wrong callback call from slider
2023-09-30 19:27:33 +02:00
Pax1601
d41dfc1e0d Fixed wrong callback call from slider 2023-09-30 19:27:16 +02:00
Pax1601
493898bd4a Merge pull request #414 from Pax1601/329-add-basic-automatic-firefight
329 add basic automatic firefight
2023-09-30 19:04:18 +02:00
Pax1601
8ebe427269 Enabled direction randomization 2023-09-30 19:03:59 +02:00
Pax1601
48d4ff97a0 Fixed elevation calculations 2023-09-30 18:53:32 +02:00
PeekabooSteam
83769bf539 Converted for plugin use 2023-09-29 18:09:38 +01:00
Pax1601
0954bf2923 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-09-29 17:21:58 +02:00
Pax1601
a2f5f82e28 Removed redundant loadout roles 2023-09-29 17:21:53 +02:00
Pax1601
a82af04fca Merge pull request #409 from Pax1601/Pax1601-patch-1
Update ci.yml
2023-09-29 15:35:03 +02:00
Pax1601
a1a876429c Update ci.yml 2023-09-29 15:34:54 +02:00
Pax1601
58830fa53e Update package-lock.json 2023-09-29 15:30:50 +02:00
Pax1601
15c8e32fef Merge pull request #408 from Pax1601/407-create-a-simple-plugin-to-manage-units-database
407 create a simple plugin to manage units database
2023-09-29 15:28:07 +02:00
Pax1601
59c915d8bc Updated lock file for checks 2023-09-29 15:26:06 +02:00
Pax1601
968ff61979 Database editor (almost) completed
Liveries editor still to add, but no one in his right mind would change them manually since we have scripts for that
2023-09-29 15:24:08 +02:00
Pax1601
94901849e6 More work on database editing 2023-09-28 17:33:38 +02:00
Pax1601
ff42126b0e Merge branch '329-add-basic-automatic-firefight' into 407-create-a-simple-plugin-to-manage-units-database 2023-09-28 09:09:02 +02:00
Pax1601
39ddf10ca7 Added code to save edited database to disk 2023-09-27 21:46:05 +02:00
Pax1601
7a24e5d39d More work on database manager 2023-09-27 17:08:15 +02:00
Pax1601
e9100504a0 More work on database manager 2023-09-25 17:35:17 +02:00
Pax1601
099cbfdf75 Added more code to handle loadouts 2023-09-24 20:03:21 +02:00
Pax1601
28afef8847 Merge branch 'main' into 407-create-a-simple-plugin-to-manage-units-database 2023-09-24 10:22:45 +02:00
Pax1601
010b1e1cce Exported definitions and fixed interfaces 2023-09-24 10:21:28 +02:00
Pax1601
274ce76c2b Basic plugin structure 2023-09-22 17:58:37 +02:00
Pax1601
f3155e618b Added target altitude effect to simulated fire fight 2023-09-22 16:05:03 +02:00
Pax1601
18307caab3 Merge branch 'main' into 329-add-basic-automatic-firefight 2023-09-22 15:15:58 +02:00
Pax1601
2e279b8876 Update .gitignore 2023-09-22 15:15:22 +02:00
Pax1601
0da878f50f Merge pull request #396 from Pax1601/391-control-tips-mouseover-option
Tips added for formations
2023-09-22 15:06:33 +02:00
Pax1601
ecfb3644be Merge pull request #403 from Pax1601/388-double-click-select-all-only-on-unselected
Unit doubleclick fixed
2023-09-22 15:05:42 +02:00
Pax1601
c87d18fd8e Merge pull request #406 from Pax1601/394-retrieve-ground-altitude-at-mouse-coordinates-location
394 retrieve ground altitude at mouse coordinates location
2023-09-22 15:03:55 +02:00
Pax1601
5810f9232a Completed ground elevation provider and added to mouse info panel 2023-09-22 15:03:35 +02:00
PeekabooSteam
fb8eb6f357 Unit doubleclick fixed 2023-09-22 08:36:07 +01:00
PeekabooSteam
7eb76ff32d Added hotgroup 2023-09-21 22:54:09 +01:00
PeekabooSteam
c3d3de9984 Conflict 2023-09-21 22:23:47 +01:00
PeekabooSteam
cc2549dbdf Tips added for formations 2023-09-21 22:19:01 +01:00
Pax1601
7efa8eab18 Added api enpoint to retrieve altitude at coordinates 2023-09-21 17:37:13 +02:00
Pax1601
376ae9ec1c Update ci.yml 2023-09-21 15:03:59 +02:00
Pax1601
9882b2999f Update ci.yml 2023-09-21 14:58:54 +02:00
Pax1601
3667a75244 Merge pull request #393 from Pax1601/Pax1601-patch-1
Update ci.yml
2023-09-21 14:53:19 +02:00
Pax1601
4089448b53 Update ci.yml 2023-09-21 14:53:09 +02:00
Pax1601
fec11869a8 Update ci.yml 2023-09-21 13:31:21 +02:00
Pax1601
e7e56d1cdb Removed caching 2023-09-21 13:28:32 +02:00
Pax1601
9db01d6060 Modified deploy 2023-09-21 13:23:39 +02:00
Pax1601
ed38397631 Removed types definitions 2023-09-21 13:17:44 +02:00
Pax1601
b3dddc0570 Added types folder 2023-09-21 13:10:39 +02:00
Pax1601
6fa06de245 Added job needs 2023-09-21 13:06:10 +02:00
Pax1601
834ddde1d0 Merged actions 2023-09-21 13:03:14 +02:00
Pax1601
5d4348f8a7 Create static.yml 2023-09-21 12:54:55 +02:00
Pax1601
36f2917995 Synced lock file 2023-09-21 11:03:03 +02:00
Pax1601
eedbec175d Fixed working directory 2023-09-21 10:58:18 +02:00
Pax1601
344ec86722 Executing workflow in client directory 2023-09-21 10:56:17 +02:00
Pax1601
952d1e5895 Added typescript dependency 2023-09-21 10:51:31 +02:00
Pax1601
a371484f38 Removed wrong workflow steps 2023-09-21 10:48:43 +02:00
Pax1601
1567a6fd27 Workflow test 2023-09-21 10:42:12 +02:00
Pax1601
e0f96b5cca Added package.json 2023-09-21 10:38:51 +02:00
Pax1601
8f6e48642c Added package-lock 2023-09-21 10:34:48 +02:00
Pax1601
0c4c10dc1a Fixed folder typo 2023-09-21 10:27:38 +02:00
Pax1601
de6b78d762 Automatic workflow test 2023-09-21 10:24:15 +02:00
Pax1601
6b77f32548 Merge pull request #392 from Pax1601/391-control-tips-mouseover-option
Can now specify a selector or a mouseover
2023-09-21 10:09:10 +02:00
Pax1601
fd2b7a00e1 Moved gun data into databases jsons, made core read from databases 2023-09-20 18:58:21 +02:00
PeekabooSteam
818886a65e Can now specify a selector or a mouseover 2023-09-20 17:30:58 +01:00
Pax1601
0ca31afc91 Merge branch 'main' into 329-add-basic-automatic-firefight 2023-09-20 17:34:02 +02:00
Pax1601
024a73da63 Merge pull request #384 from Pax1601/poc-plugins-v1
Poc plugins v1
2023-09-20 16:27:29 +02:00
Pax1601
744b0063d8 Merge pull request #390 from Pax1601/308-desired-speed-sliders-dots-not-showing-in-client
Fix issue #308 - remove color-mix and set precomputed css variable value
2023-09-20 16:26:29 +02:00
amouillard
355923f680 Fix issue #308 - remove color-mix and set precomputed css variable value 2023-09-20 16:19:24 +02:00
Pax1601
44332a2004 Moved server code to dedicated ServerManager class 2023-09-18 17:10:14 +02:00
Pax1601
2f125e3d0e Completed plugins framework
More work required to define all interfaces for the useful classes in the @types folder
2023-09-15 23:07:15 +02:00
Pax1601
588228c050 Implemented basic Plugin handling 2023-09-15 17:05:26 +02:00
Pax1601
8977ba9b6d Added basic simulated firefight state 2023-09-15 09:36:27 +02:00
PeekabooSteam
ad06117b78 Refined a bit more. 2023-09-14 21:10:52 +01:00
PeekabooSteam
01b30ccf12 Refined the options a bit. 2023-09-14 20:56:34 +01:00
PeekabooSteam
7f75905d5d Resolved conflicts 2023-09-14 18:59:20 +01:00
PeekabooSteam
798856c649 Nearly final commit of control tips' v1 2023-09-14 17:55:01 +01:00
Pax1601
9acd358080 Merge pull request #383 from Pax1601/374-right-click-drag-error
Fix issue #374
2023-09-13 19:15:27 +02:00
amouillard
31c112157a Fix issue #374 2023-09-13 18:47:24 +02:00
PeekabooSteam
d2e162edbf Removed directory creation. 2023-09-12 19:07:36 +01:00
PeekabooSteam
6aaffe20d9 Plugin (not) work. 2023-09-12 19:04:52 +01:00
Pax1601
6d32b20117 More documentation 2023-09-12 17:54:59 +02:00
Pax1601
bd894704b1 v0.4.4 2023-09-10 17:26:33 +02:00
Pax1601
7af2162b50 Merge pull request #379 from Pax1601/368-spawn-points-can-integer-overflow-on-the-server-side
Switched from unsigned int to int for spawn points
2023-09-09 19:15:34 +02:00
Pax1601
c735d108d4 Merge pull request #378 from Pax1601/refactor
Refactor
2023-09-09 19:08:31 +02:00
Pax1601
6a2ffc936e More bugfixing, set CAS and ASL to be default modes 2023-09-09 19:07:09 +02:00
Pax1601
74d5480587 Minor refactor and bug fixing 2023-09-08 22:41:37 +02:00
Pax1601
89c39c7038 Code documentation and refactoring 2023-09-08 17:40:53 +02:00
Pax1601
61f955cfeb Added copy ability in RTS mode 2023-09-08 16:25:12 +02:00
Pax1601
744adee94c Merge branch 'main' into 345-allow-for-copy-and-paste-in-rts-mode 2023-09-07 16:56:55 +02:00
Pax1601
267c0b037d Merge branch 'main' into 345-allow-for-copy-and-paste-in-rts-mode 2023-09-07 13:03:50 +02:00
Pax1601
860414b7b2 Merge pull request #377 from Pax1601/370-write-better-method-of-determining-if-a-command-has-been-completed
370 write better method of determining if a command has been completed
2023-09-07 13:03:05 +02:00
Pax1601
09bf361d44 Added ability to delete original cloned units
Mostly useful to group units together
2023-09-07 13:02:14 +02:00
Pax1601
e2f80c5788 Fixed table deepcopy 2023-09-06 20:19:47 +02:00
Pax1601
a96a6eb57d Added command hash control 2023-09-05 17:25:32 +02:00
PeekabooSteam
803f9a7fd6 Started working on shurtcuts plugin 2023-09-05 09:43:36 +01:00
Pax1601
71a141e0b8 Merge pull request #373 from Pax1601/372-pan-up-doesnt-work-via-keyboard
Pan up now pans
2023-09-05 09:42:55 +02:00
PeekabooSteam
a99b85e646 More plugin design 2023-09-04 23:56:48 +01:00
PeekabooSteam
333169d18c Pan up now pans 2023-09-04 22:57:32 +01:00
PeekabooSteam
a08eb418a6 Stash commit to open a new branch. 2023-09-04 22:54:01 +01:00
Pax1601
cbb878cf96 Fixed errors in lua clone units 2023-09-04 21:44:22 +02:00
Pax1601
d684f91a5a Merge branch '370-write-better-method-of-determining-if-a-command-has-been-completed' into 345-allow-for-copy-and-paste-in-rts-mode 2023-09-04 19:02:10 +02:00
Pax1601
f2de4cd34c Completed implementation 2023-09-04 19:01:50 +02:00
Pax1601
3d076a605b Merge branch '370-write-better-method-of-determining-if-a-command-has-been-completed' into 345-allow-for-copy-and-paste-in-rts-mode 2023-09-04 17:31:58 +02:00
Pax1601
3607f88e18 Converted clone function to pure lua 2023-09-04 17:27:09 +02:00
Pax1601
a0d2bb11ed Switched from unsigned int to int for spawn points 2023-09-04 16:06:41 +02:00
Pax1601
ede245a37d Implemented executed commands provider 2023-09-04 12:41:54 +02:00
Pax1601
aca1e112d2 Merge pull request #371 from Pax1601/369-coalition-colour-incorrectly-set-on-spawn-menu-in-rts-mode
Minor bugfix
2023-09-04 11:00:46 +02:00
Pax1601
bf5d6dac18 Minor bugfix 2023-09-04 11:00:28 +02:00
Pax1601
182ce4da42 Hotfix 2023-09-03 17:55:58 +02:00
Pax1601
41e2e6fa59 Updated documentation 2023-09-03 16:45:48 +02:00
Pax1601
fe0e964a5a Merge pull request #367 from Pax1601/343-add-ability-to-select-unit-nation-and-livery
v0.4.4
2023-09-03 16:34:34 +02:00
Pax1601
bee35f9ee9 v0.4.4 2023-09-03 16:34:11 +02:00
Pax1601
e66a1bb5b4 Merge pull request #366 from Pax1601/343-add-ability-to-select-unit-nation-and-livery
343 add ability to select unit nation and livery
2023-09-03 16:32:06 +02:00
Pax1601
8490997604 Merge branch 'main' into 343-add-ability-to-select-unit-nation-and-livery 2023-09-03 15:18:35 +02:00
Pax1601
6898d1df6d Completed unit nation selection and new spawn menu 2023-09-03 15:15:11 +02:00
PeekabooSteam
4d863bb894 First commit 2023-09-03 12:08:35 +01:00
Pax1601
a338e5fa26 Added docs folder 2023-09-01 16:44:47 +02:00
Pax1601
695adc8acb More work on units spawn menu and started to add documentation 2023-09-01 16:13:15 +02:00
Pax1601
fab7d26191 More work on scripted spawn menu 2023-08-31 17:25:47 +02:00
Pax1601
3959139dd8 Started conversion to scripted unit spawn menu 2023-08-30 20:01:25 +02:00
Pax1601
1298669f1c Merge pull request #365 from Pax1601/358-right-click-long-press-for-unit-action-context-menu
358 right click long press for unit action context menu
2023-08-30 09:13:13 +02:00
Pax1601
4fe40f5ff7 Merge branch 'main' into 358-right-click-long-press-for-unit-action-context-menu 2023-08-30 09:13:06 +02:00
Pax1601
a10c113c42 Right click long press menu completed 2023-08-30 09:10:42 +02:00
Pax1601
d5f4b5c711 More work on country selection 2023-08-29 19:17:36 +02:00
Pax1601
93707af56b Merge pull request #363 from Pax1601/350-in-rts-mode-helicopters-are-shown-with-a-distinctive-shape-that-allows-to-identify-them
Non visually detected units are now drawn with generic symbol
2023-08-29 14:59:42 +02:00
Pax1601
0ae694c1a8 Non visually detected units are now drawn with generic symbol 2023-08-29 14:59:23 +02:00
Pax1601
0b53fb19b7 Merge pull request #362 from Pax1601/356-add-marker-for-deployed-smoke
Create colored smoke markers
2023-08-29 10:02:50 +02:00
Pax1601
cc386e86b9 Create colored smoke markers 2023-08-29 10:02:18 +02:00
Pax1601
a922d7de31 Merge pull request #361 from Pax1601/349-add-ability-to-hide-units-names
349 add ability to hide units names
2023-08-29 09:39:27 +02:00
Pax1601
8e7d64f0e4 Remove shortcut and added option in dropdown 2023-08-29 09:39:07 +02:00
Pax1601
0bc406538b Merge pull request #360 from Pax1601/351-double-click-on-a-unit-should-select-all-units-of-that-time-on-the-screen
351 double click on a unit should select all units of that time on the screen
2023-08-28 17:14:23 +02:00
Pax1601
9547559e00 Refactoring and merge 2023-08-28 17:14:03 +02:00
Pax1601
70783dc828 Merge branch 'main' into 351-double-click-on-a-unit-should-select-all-units-of-that-time-on-the-screen 2023-08-28 17:05:34 +02:00
Pax1601
85bdd791b8 Implemented long press right click menu 2023-08-28 15:48:46 +02:00
Pax1601
9d7e61556d Added unit country selection 2023-08-27 15:59:50 +02:00
Pax1601
4d954688a9 v0.4.3 2023-08-26 10:58:51 +02:00
Pax1601
eb80c39b98 Loadouts changes and spawn menu update 2023-08-24 16:16:59 +02:00
Pax1601
b1e4dd62b0 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-08-15 15:02:52 +02:00
Pax1601
9db07b2ff8 Reordered scripts folder 2023-08-15 15:02:49 +02:00
Pax1601
df432b1635 Merge pull request #355 from Pax1601/208-fix-airport-info-and-spawn-menu-1
Moved code from broken branch.
2023-08-15 12:26:49 +02:00
Pax1601
e96cb2716d Moved airfields database to public/database folder 2023-08-15 12:26:05 +02:00
Pax1601
3055378b86 Minimal code refactoring 2023-08-15 11:19:44 +02:00
Pax1601
e4b34b1dbc Merge pull request #354 from Pax1601/348-ctrl+click-on-units-on-the-units-control-panel-should-remove-them-from-the-list
Ctrl-click-deselect
2023-08-15 11:09:40 +02:00
Pax1601
f544b0afaa Minimal code refactoring 2023-08-15 11:09:00 +02:00
PeekabooSteam
06e1cbeb7e Changed events to use pre-existing names 2023-08-14 23:12:14 +01:00
PeekabooSteam
6da84dd7b0 Moved code from broken branch. 2023-08-13 15:34:59 +01:00
PeekabooSteam
07b69fe96f Added dbl-click select but it's buggy AF 2023-08-12 19:31:08 +01:00
PeekabooSteam
94b8a9270d Ctrl-click-deselect 2023-08-12 17:45:38 +01:00
PeekabooSteam
e0a3fd1795 Corrected some variable names. 2023-08-12 16:46:37 +01:00
Pax1601
14552913a3 Merge pull request #352 from Pax1601/343-add-ability-to-select-unit-nation-and-livery
343 add ability to select unit nation and livery
2023-08-12 12:37:21 +02:00
Pax1601
a76ab8e037 Removed debug flag 2023-08-12 12:32:40 +02:00
Pax1601
6c496e428f Added costs to blueprints 2023-08-12 12:31:28 +02:00
Pax1601
46ca6ac327 Merge branch 'main' into 343-add-ability-to-select-unit-nation-and-livery 2023-08-10 17:52:43 +02:00
Pax1601
27d77f97db Added livery ID 2023-08-10 17:50:10 +02:00
Pax1601
f24d7277a0 Update README.md 2023-08-04 19:09:29 +02:00
Pax1601
94d2ce7fbe Minor bugfixing on unit visibility 2023-08-04 19:07:46 +02:00
Pax1601
9391e78b16 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-08-04 12:56:05 +02:00
Pax1601
902e4a45ac Updated version number 2023-08-04 12:55:46 +02:00
Pax1601
67b2ceeee7 Merge pull request #344 from Pax1601/bugfixing
Bugfixing
2023-08-04 12:53:48 +02:00
Pax1601
f111e513c5 More bugfixing 2023-08-04 12:53:14 +02:00
Pax1601
2f839624a8 More frontend bugfixing 2023-08-04 11:05:21 +02:00
Pax1601
187fcd3d85 Moved unit databases outside of source and started adding country flags 2023-08-02 12:11:07 +02:00
Pax1601
66f08e8fce Fixed ROEs 2023-07-31 14:08:36 +02:00
Pax1601
f97b1e5f47 Merge pull request #332 from WoodyXP/331-Fix-AH-64-Loadout-Issue
Updated the Apache loadout with the correct CLSIDs
2023-07-31 10:05:07 +02:00
Pax1601
c3b4c4ae36 Multiple bugfixes 2023-07-31 08:08:20 +02:00
Pax1601
fd7f4b9772 Multiple bug fixes and optimizations 2023-07-28 17:43:31 +02:00
Pax1601
bac2c430ef Merge pull request #342 from Pax1601/340-dont-install-development-node-modules
Added package command to prune dev modules
2023-07-27 19:22:35 +02:00
Pax1601
3f1c9942c3 Merge pull request #341 from Pax1601/333-missiles-and-bombs-are-not-being-exported
333 missiles and bombs are not being exported
2023-07-27 19:22:08 +02:00
Pax1601
80ed675cbc Completed transition to weapons handler 2023-07-27 19:21:34 +02:00
Pax1601
6d434e48a1 Added missing files 2023-07-27 17:16:21 +02:00
Pax1601
7961870ac4 Added package command to prune dev modules 2023-07-27 17:15:57 +02:00
Pax1601
0150ae9df1 Splitted weapons and units managers 2023-07-27 16:27:59 +02:00
Pax1601
875f3ebe68 Added handler to detect units and weapons creation 2023-07-26 22:39:26 +02:00
Pax1601
3fac8a5663 Fixed missing isAlive value 2023-07-26 10:58:39 +02:00
Pax1601
3c11e1c2a1 Front end tweaks 2023-07-25 17:54:26 +02:00
Pax1601
81871b596b Completed backend for advanced RTS functions 2023-07-23 22:30:25 +02:00
Pax1601
8ffd5ef972 Started to add advanced RTS options to backend 2023-07-21 19:51:23 +02:00
Pax1601
4ae72b7c0b Front end tweaks
Added visibility options and server log panel
2023-07-21 17:33:24 +02:00
Pax1601
5613394a2c Completed RTS front end 2023-07-20 17:49:41 +02:00
Pax1601
2e113b468a Merge branch 'performance-optimization' into 326-add-advanced-rts-options 2023-07-20 11:02:26 +02:00
Pax1601
018e37cd2a Minor graphic tweaks 2023-07-20 10:59:48 +02:00
Pax1601
1d5f24dc1a Added check on repeated commands on scheduler 2023-07-19 20:56:19 +02:00
Pax1601
cbb8920de7 Styled the server load panel 2023-07-19 17:41:05 +02:00
Pax1601
7eb6cadc4e Merge remote-tracking branch 'origin/performance-optimization' into 326-add-advanced-rts-options 2023-07-19 17:03:35 +02:00
Pax1601
a4db569fbd Performance optimizations for large unit counts 2023-07-18 21:56:56 +02:00
WoodyXP
2582dfd3c3 Updated the Apache loadout with the correct CLSIDs 2023-07-16 01:15:10 +02:00
Pax1601
e9a3ecb9eb Started to implement RTS advanced options 2023-07-13 17:52:05 +02:00
Pax1601
785647ad24 Merge branch 'pr/325' 2023-07-13 11:28:43 +02:00
WoodyXP
72cd4de55f Added the correct name for every naval unit 2023-07-12 19:08:24 +02:00
WoodyXP
e882123692 Removed naval units mods 2023-07-12 17:08:08 +02:00
Pax1601
a949a9bf22 Tweaks and implemented workaround to MIST bug 2023-07-12 17:01:03 +02:00
WoodyXP
75c897eb5b Change function to filter by era due to change of value type 2023-07-12 16:41:55 +02:00
WoodyXP
b48f74f879 Added coalition to naval units 2023-07-12 16:31:46 +02:00
WoodyXP
c6eeeac7c1 Added coaltion to helicopter units 2023-07-12 15:50:14 +02:00
WoodyXP
9c1edd2a86 Added coalition to groundunits and fixed some eras and reformatted aircraft db 2023-07-12 15:43:13 +02:00
WoodyXP
133c447d5d Added coalition to aircraftdatabase.ts and switched era list to string 2023-07-12 14:57:15 +02:00
Pax1601
b78cd27e4e Merge pull request #323 from Pax1601/319-add-basic-rts-functions
319 add basic rts functions
2023-07-11 18:56:57 +02:00
Pax1601
5d29c82244 Commented not implemented functions 2023-07-11 18:56:37 +02:00
Pax1601
f379f6b998 Tweaks to IADS creation and menus 2023-07-11 17:30:05 +02:00
Pax1601
439111f7a0 Merge branch 'main' into 319-add-basic-rts-functions 2023-07-11 14:34:59 +02:00
Pax1601
55372d5a5b Merge pull request #322 from WoodyXP/321-Adding-Era-To-Helicopter-DB
Added era to all helicopter units
2023-07-11 14:30:09 +02:00
Pax1601
13e3b93e93 More tweaks on frontend 2023-07-10 16:58:54 +02:00
WoodyXP
7a6929e34b Added era to all helicopter units 2023-07-10 14:07:12 +02:00
Pax1601
a0763a6450 Minor tweaks and fixes 2023-07-09 18:48:21 +02:00
Pax1601
2d4202979f Merge branch '312-add-ability-to-draw-areas-and-fill-with-iads' into 319-add-basic-rts-functions 2023-07-07 17:27:20 +02:00
Pax1601
327d5c74d9 Add basic visibility functions and ability to spawn multiple units in group 2023-07-07 17:26:41 +02:00
Pax1601
3bad83a02f Merge pull request #316 from WoodyXP/313-fix-getByRange-function
Changed the function that it gets all the units with a specified range
2023-07-06 13:10:17 +02:00
Pax1601
eee97294df Merge branch 'main' into 313-fix-getByRange-function 2023-07-06 13:10:10 +02:00
Pax1601
56427d84ad Merge pull request #317 from WoodyXP/131-add-navalunitdb
131 add navalunitdb
2023-07-06 13:08:48 +02:00
Pax1601
fc1983d554 Merge pull request #318 from Pax1601/312-add-ability-to-draw-areas-and-fill-with-iads
312 add ability to draw areas and fill with iads
2023-07-06 13:00:14 +02:00
Pax1601
30568e54f7 Converted demo data creation to binary data 2023-07-06 12:59:08 +02:00
Pax1601
1af98cc54f Tweaks and optimizations of front end 2023-07-05 20:14:48 +02:00
Stefan Arsic
fb3a628ad0 Update unitPayloads.lua 2023-07-05 18:55:47 +02:00
Stefan Arsic
79b0eeae9e Update unitPayloads.lua 2023-07-05 18:49:53 +02:00
WoodyXP
3b2757a022 Added all ship to the naval database and made a function to filter by ship type 2023-07-05 18:47:02 +02:00
WoodyXP
fa9f1e05ea Updated the navalunitdb and added new type range into unit types 2023-07-04 17:36:23 +02:00
WoodyXP
fff0c8244e Merge branch 'main' into 131-add-navalunitdb 2023-07-04 16:32:54 +02:00
Stefan Arsic
5777632114 Create navalunitdatabase.ts 2023-07-04 14:04:08 +02:00
WoodyXP
d013337c5e Changed the function that it gets all the units with a specified range 2023-07-03 19:06:40 +02:00
Pax1601
ec91376da2 More fixes in binary data transmission 2023-07-02 22:13:53 +02:00
Pax1601
807cdfeb5b Added code to update ammo and contacts 2023-07-01 12:31:30 +02:00
Pax1601
9f6da4845a Merge pull request #315 from WoodyXP/313-add-sam-information-V2
Added Era and Range to Sams and Ground Units V2
2023-06-29 17:16:45 +02:00
Pax1601
211cf48681 More fixes on binary data transmission 2023-06-29 08:10:14 +02:00
Pax1601
4d9dd364b6 Converted data transfer to binary key-value method 2023-06-26 18:53:04 +02:00
Stefan Arsic
52dfcebc14 Update groundunitsdatabase.ts 2023-06-26 14:14:53 +02:00
Stefan Arsic
2bce51fca6 Update groundunitsdatabase.ts 2023-06-26 14:14:21 +02:00
Stefan Arsic
3a2048f3ec Updated Era 2023-06-26 14:12:57 +02:00
Stefan Arsic
63e602afb1 Fixed some more era types 2023-06-26 09:24:02 +02:00
Stefan Arsic
7a71065b76 Fixed Typo and Era type 2023-06-26 09:21:11 +02:00
Pax1601
1989219579 Fixed update error and added update trigger 2023-06-25 19:04:12 +02:00
Pax1601
dd2e858db4 More work on client conversion to binary data 2023-06-23 17:32:38 +02:00
Pax1601
916752301a Started transition to binary data on client side 2023-06-22 22:17:00 +02:00
Pax1601
1d62b4c115 Transition to json to binary data transfers 2023-06-22 17:28:40 +02:00
WoodyXP
258f1136e2 Added Era and Range to Sams and Ground Units V2 2023-06-22 16:10:48 +02:00
Pax1601
9d0e2239e4 Added new method for handling data 2023-06-21 20:05:41 +02:00
WoodyXP
5555c44c4e Merging pax main 2023-06-21 18:26:12 +02:00
WoodyXP
f80a91ca1e Fixing Merge conflict 2023-06-21 18:20:01 +02:00
Pax1601
61d6d9f16c Added better temporary markers and more map functions 2023-06-20 17:36:21 +02:00
Pax1601
635c487c2b Added area editing functions 2023-06-19 17:14:53 +02:00
Pax1601
f9f02c3eb0 Added more functions to edit Coalition Areas 2023-06-18 19:55:01 +02:00
Pax1601
ad3b1cb167 Added basic ability to draw poligons 2023-06-16 17:32:09 +02:00
Pax1601
ca7c52ff67 Fixed error in mouse coordinates
Will need refining
2023-06-13 17:58:43 +02:00
Pax1601
feae9a4806 Minor bugfixes 2023-06-13 17:42:18 +02:00
Pax1601
6c24533393 Merge branch '153-add-ability-to-take-control-of-existing-units-from-me' 2023-06-13 17:07:21 +02:00
Pax1601
4f2debeb4f Added ability to take control of units
And bugfixes
2023-06-13 17:03:04 +02:00
Pax1601
27b56deb45 Merge pull request #302 from Pax1601/Advanced-spawn-and-control-options
Advanced spawn and control options
2023-06-12 10:00:29 +02:00
Pax1601
1d4ecf5316 Completed advanced controls also for units 2023-06-11 18:21:12 +02:00
Pax1601
fd00cffa15 Added backend for advanced commands 2023-06-06 17:27:11 +02:00
Pax1601
ab3a017b55 Minor change in distance representation 2023-06-06 14:53:46 +02:00
Pax1601
f84ff1c7b2 Merge branch 'Minor-bugfixes' into Advanced-spawn-and-control-options 2023-06-06 12:52:02 +02:00
Pax1601
1d20a3b017 Common unit functions moved to unit class 2023-06-06 12:50:18 +02:00
Pax1601
dca3438db0 Added backend for altitude type, onOff, follow roads and explosion 2023-06-05 21:22:22 +02:00
Pax1601
6c52f4de59 Added front end for area attacks 2023-06-05 17:30:37 +02:00
Pax1601
d508263f9e Minor fixes and mouse measuring restyle 2023-06-05 16:21:49 +02:00
Pax1601
ec0b179e32 Fixed confirmation menu for human deletion 2023-06-01 17:33:18 +02:00
Pax1601
0bc2fc592f Merge branch 'main' into Advanced-spawn-and-control-options 2023-06-01 17:30:38 +02:00
Pax1601
601cf35556 Merge branch 'main' into Advanced-spawn-and-control-options 2023-06-01 17:25:01 +02:00
Pax1601
156c730352 Merge pull request #300 from Pax1601/61-allow-for-spawning-of-pre-made-ground-unit-groups
Added more templates for sam sites
2023-06-01 17:22:19 +02:00
Pax1601
83f87f1e16 Added more templates for sam sites 2023-06-01 17:22:01 +02:00
Pax1601
1dd4014e61 Completed frontend controls 2023-06-01 17:18:14 +02:00
Pax1601
ed2a9d9155 Merge pull request #299 from Pax1601/bobprofisker-patch-1
Add files via upload
2023-06-01 15:58:48 +02:00
bobprofisker
bf006e725a Add files via upload
I haven't checked this works verbatim on my PC, worked on the server but bundled both files together as one for ease and didn't check it didn't error, can't see why it would though pretty simple and correct for our server will let the olympus parrots speak.
2023-05-30 21:45:03 +01:00
Pax1601
4087dbde21 Minor optimizations 2023-05-29 17:09:06 +02:00
Pax1601
982ff838a6 Merge pull request #298 from Pax1601/296-create-airbases-api
296 create airbases api
2023-05-29 15:20:17 +02:00
PeekabooSteam
8d2583264e Merge branch 'main' into 296-create-airbases-api 2023-05-29 13:44:14 +01:00
Pax1601
2db035457c Merge pull request #281 from Pax1601/164-add-confirmation-message-when-deleting-a-player
Added (crude) confirm function
2023-05-29 14:38:00 +02:00
Pax1601
7989ec2ca5 Merge pull request #297 from Pax1601/To-add-airfield-JSON-files-2023_05_24
To add airfield json files 2023 05 24
2023-05-29 14:36:10 +02:00
Pax1601
9d4f55a157 Merge pull request #294 from Pax1601/293-replace-missing-atc-images
Icons now back
2023-05-29 14:35:45 +02:00
PeekabooSteam
a56db1bdfe Merge branch 'main' into 296-create-airbases-api 2023-05-29 12:10:10 +01:00
PeekabooSteam
64ff5ce539 Airbases API added 2023-05-29 12:08:21 +01:00
Pax1601
45bb49cfe1 Added switch toggle 2023-05-27 10:06:34 +02:00
PeekabooSteam
669ec358ac Icons now back 2023-05-25 21:17:17 +01:00
PeekabooSteam
3ff182e200 Merge pull request #280 from Pax1601/278-put-real-mission-times-into-atc
278 put real mission times into atc
2023-05-24 23:33:44 +01:00
PeekabooSteam
4b709ce33b Conflict resolution 2023-05-24 23:32:53 +01:00
PeekabooSteam
a5a2a803c6 Fixed casing. 2023-05-24 23:13:47 +01:00
PeekabooSteam
e6d642994c Improved check for humans 2023-05-24 21:55:09 +01:00
PeekabooSteam
4e9eab2cce Warning now only shows when humans are in the selection. 2023-05-24 21:38:35 +01:00
Stefan Arsic
e4e9e44eea Create persiangulf.json 2023-05-24 18:34:03 +02:00
Pax1601
9586910f03 Added AGL/ASL switch 2023-05-24 17:37:41 +02:00
Shredmetal
f26dfa5011 Update caucasus.json to match airfield names with game files 2023-05-24 22:24:50 +08:00
Shredmetal
f9aae2bccf Add Nevada airfield data 2023-05-24 22:19:16 +08:00
Shredmetal
bdff79c725 Merge pull request #291 from Pax1601/main
Minor fixes (merging from main)
2023-05-24 22:18:14 +08:00
Pax1601
ec872e181d Minor fixes 2023-05-24 15:15:44 +02:00
Shredmetal
1c86002ca5 Merge pull request #290 from Pax1601/main
Merge main commits into airfield JSON addition branch
2023-05-24 18:35:18 +08:00
Shredmetal
3ee6c57d33 Added Marianas, fixed ICAO for Akrotiri 2023-05-24 18:32:55 +08:00
Pax1601
5f2f2a83dd Merge pull request #279 from Pax1601/coalitionChecker
Add files via upload
2023-05-24 11:09:21 +02:00
Pax1601
1b0a0825e6 Merge pull request #288 from Pax1601/273-add-ability-for-units-to-retain-relative-position
273 add ability for units to retain relative position
2023-05-24 11:08:27 +02:00
Pax1601
3009a73a66 Completed transition to injected svgs 2023-05-24 11:07:41 +02:00
Pax1601
e7ce9ac76d More svg injection, removing stringed html from code 2023-05-24 08:21:04 +02:00
Stefan Arsic
80a4ea1ab9 Create caucasus.json 2023-05-23 20:33:08 +02:00
Shredmetal
5dd9ed42b0 Added syria airfield data 2023-05-24 01:33:33 +08:00
Shredmetal
5c5fa928e7 Delete client/src/airfield_data directory 2023-05-24 01:32:23 +08:00
Shredmetal
2597fb659f Rename syria_airfields.json to syriaAirfields.json 2023-05-24 01:31:54 +08:00
Shredmetal
d4d28d39ae Add files via upload
JSON file containing information on all airfields on the Syria map
2023-05-24 00:26:12 +08:00
Pax1601
a2664dc676 Refactoring of files and more svg tidy up 2023-05-22 17:39:33 +02:00
Pax1601
32cb147a02 More restyling with svg images 2023-05-22 08:22:50 +02:00
PeekabooSteam
05a8085e06 ATC now 'live'; added visual improvemnts. 2023-05-20 22:17:04 +01:00
bobprofisker
0392c43835 Add files via upload
Wasn't sure if you were serious about wanting the code for how to get all the coalitions out of the mission file, this is how you do it and how you can get a string for what it actually is if that is needed.
2023-05-20 22:16:41 +01:00
Pax1601
a6583cc317 Added resources router 2023-05-19 21:20:33 +02:00
Pax1601
bf88c9b951 Implemented group destination spacing 2023-05-19 14:38:28 +02:00
Pax1601
9cc0058e32 Minor graphic tweaks 2023-05-19 09:17:11 +02:00
Pax1601
9eb295d9a1 Added auto selection of units in group 2023-05-18 17:48:03 +02:00
Pax1601
10d250e3a5 Added basic template spawning 2023-05-18 09:09:20 +02:00
PeekabooSteam
2b155c4ed3 ATC clocks now synched to mission time 2023-05-17 19:36:12 +01:00
PeekabooSteam
4a93c1eead Added (crude) confirm function 2023-05-17 16:59:36 +01:00
Pax1601
0b490e4ce2 Merge pull request #277 from Pax1601/264-add-avanced-unit-control-options
264 add avanced unit control options
2023-05-17 16:17:33 +02:00
Pax1601
03a8c93e9e Added advanced unit controls
Radio, ECM, countermeasures and prohibits
2023-05-17 16:17:17 +02:00
Pax1601
84cca6b9d1 Merge pull request #276 from Pax1601/Update-UnitDataBase-and-AircraftDatabase-(DO-NOT-MERGE-WITHOUT-TESTING)
Update unit data base and aircraft database (do not merge without testing)
2023-05-17 12:07:52 +02:00
Pax1601
0f353641ed Merge branch 'main' into Update-UnitDataBase-and-AircraftDatabase-(DO-NOT-MERGE-WITHOUT-TESTING) 2023-05-17 12:07:37 +02:00
Pax1601
16c37a3445 Merge pull request #275 from Pax1601/271-add-unit-hotgroups
271 add unit hotgroups
2023-05-17 11:43:34 +02:00
Pax1601
25d411b1be Completed hotgroups
Single hotgroup per unit
2023-05-17 11:43:14 +02:00
Pax1601
493c75b6e7 Added hotgroups ui and basic functions
User interaction still TBD
2023-05-15 17:37:20 +02:00
Pax1601
1ca2c66b45 Merge pull request #270 from Pax1601/v0.2.2-fixes
Fixed #261 and #262
2023-05-15 15:09:23 +02:00
Pax1601
772c065a73 Fixed #261 and #262 2023-05-15 15:08:56 +02:00
Pax1601
71ef292763 Added frontend controls for emissions and countermeasures 2023-05-11 17:24:56 +02:00
Pax1601
98a6053a85 v0.2.1 release 2023-05-10 17:07:26 +02:00
Pax1601
7d3debfa7a Merge pull request #259 from Pax1601/221-dont-allow-to-give-tasks-to-human-players
Removed options to command human units
2023-05-10 16:54:52 +02:00
Pax1601
847234633a Removed options to command human units 2023-05-10 16:54:36 +02:00
Pax1601
47d9ff2e10 Merge pull request #258 from Pax1601/236-clean-up-server-from-dead-units
Optimized transmission of data of dead units
2023-05-10 16:14:15 +02:00
Pax1601
e69294b98c Optimized transmission of data of dead units
Dead units only transmit basedata. Empty fields and empty units are removed from update packages.
2023-05-10 16:13:55 +02:00
Pax1601
cf3cdcbd44 Merge pull request #257 from Pax1601/210-fix-ordinance-indicators-below-unit-markers
Ordnance markers are now painted correctly
2023-05-10 11:50:44 +02:00
Pax1601
7545e848d6 Ordnance markers are now painted correctly 2023-05-10 11:50:26 +02:00
Pax1601
d146a47e71 Merge pull request #255 from Pax1601/38-user-authentication-missing
38 user authentication missing
2023-05-10 08:59:21 +02:00
Pax1601
91f8996fba Implemented basic authentication
Also fixed Tankers and AWACS which now operate as expected
2023-05-10 08:59:02 +02:00
Pax1601
57b74bd1b1 Added frontend code for authentication 2023-05-09 15:41:04 +02:00
Pax1601
865be6283c Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-05-05 17:12:16 +02:00
Pax1601
e0636b53f0 Added tristate coalition switch 2023-05-05 17:11:28 +02:00
Pax1601
987c8ee41c Merge pull request #254 from Pax1601/216-increase-ui-reactivity
Removed 200ms delay and small UI fixes
2023-05-04 17:34:08 +02:00
Pax1601
e54a70ffa8 Removed 200ms delay and small UI fixes 2023-05-04 17:32:55 +02:00
Pax1601
fcf1e2d94a Merge pull request #253 from Pax1601/186-style-dropdown-scrollbars
Partially styled, fixed custom fonts
2023-05-04 16:03:47 +02:00
Pax1601
35648b67f5 Partially styled, fixed custom fonts 2023-05-04 16:03:28 +02:00
Pax1601
f0dc581261 Merge pull request #252 from Pax1601/217-dropdowns-dont-close-when-clicking-outside-of-them
Dropdowns now close when clicking outside of them
2023-05-04 09:54:43 +02:00
Pax1601
7ecfc5afef Dropdowns now close when clicking outside of them 2023-05-04 09:54:26 +02:00
Pax1601
e3b88d4e35 Merge pull request #251 from Pax1601/220-add-temporary-marker-for-units-spawning
Added temporary spawn marker
2023-05-03 19:15:21 +02:00
Pax1601
669ee510d3 Added temporary spawn marker 2023-05-03 19:15:00 +02:00
Pax1601
b8edc500c4 Merge pull request #250 from Pax1601/241-ground-units-can-not-be-copy-pasted
Ground units can now be copy-pasted
2023-05-03 10:08:37 +02:00
Pax1601
dc57028a3c Ground units can now be copy-pasted 2023-05-03 10:07:38 +02:00
Pax1601
9eb01654c6 Merge pull request #249 from Pax1601/213-request-spawn-on-airfield
Takeoff task changed to TakeoffParkingHot
2023-05-03 09:22:21 +02:00
Pax1601
8539314984 Takeoff task changed to TakeoffParkingHot 2023-05-03 09:22:00 +02:00
Pax1601
cb24a19d17 Small fixes to map panning 2023-05-02 15:50:55 +02:00
Pax1601
bd7700efce Merge pull request #248 from Pax1601/245-map-cant-be-panned-with-arrows-if-unit-is-selected
Multiple map panning fixes and improvements
2023-05-02 14:30:59 +02:00
Pax1601
a23bdd4b33 Multiple map panning fixes and improvements 2023-05-01 21:51:46 +02:00
Pax1601
7427c7059c Fixed error due to missing declarations 2023-05-01 11:12:21 +02:00
Shredmetal
d32923ffe8 Added AircraftDatabase with era
DO NOT MERGE WITHOUT TESTING. This will break olympus as of the date of upload.
2023-05-01 17:05:16 +08:00
Pax1601
89a71ef04e Merge pull request #243 from Pax1601/209-update-follow-functionality-for-ordering-units
209 update follow functionality for ordering units
2023-05-01 10:37:59 +02:00
Pax1601
640f764354 Implemented as described in issue 2023-05-01 10:37:40 +02:00
Shredmetal
2dad717a42 Updated GroundUnitsDatabase
This will cause the current build to crash as it does not recognise the "effective_target" key: value pair. Do not merge into main until this has been addressed.
2023-05-01 15:54:36 +08:00
Pax1601
ee08d9d48e Started work on better follow functionality
And other minor fixes
2023-04-28 17:32:28 +02:00
Pax1601
bf365270ae Merge pull request #230 from Pax1601/218-add-humandcs-controlledolympus-controller-icon
218 add humandcs controlledolympus controller icon
2023-04-28 15:43:22 +02:00
Pax1601
6ec2235114 Fixed units jumping back 2023-04-27 16:06:08 +02:00
Pax1601
8f7071510b Merge pull request #225 from Shredmetal/Add-loadouts-to-aircraftdatabase-and-unipayloads-22/4
Add files via upload
2023-04-27 12:27:48 +02:00
Shredmetal
1f72612255 Add files via upload
fixed issues with the tomcat loadouts in use - ISSUE WILL RESURFACE IF NEW LOADOUTS ADDED. Remember to change the unitPayloads lua together with the AircraftDatabase
2023-04-27 02:45:04 +08:00
Shredmetal
94c5765bc6 Add files via upload
fixed references to aircraftdatabase
2023-04-27 02:43:08 +08:00
Pax1601
04c7fc3741 Added human and DCS controlled icons 2023-04-26 17:42:17 +02:00
Pax1601
40bcd46677 Added minimap and scale 2023-04-26 16:49:01 +02:00
Shredmetal
ab736adabe Add files via upload
Helicopterdatabase
2023-04-26 05:19:55 +08:00
Pax1601
f4fd516d92 Merge pull request #214 from Shredmetal/Add-loadouts-to-aircraftdatabase-and-unipayloads-22/4
Changed aircraftdatabase.ts and unitpayloads.lua
2023-04-24 19:23:03 +02:00
Shredmetal
4c3cfc608b Add files via upload
Added MiG-21Bis Fox-1 only loadout
2023-04-24 18:54:47 +08:00
Shredmetal
6ae23509a6 Add files via upload
added MiG-21Bis loadout, fox 1 only
2023-04-24 18:53:49 +08:00
Shredmetal
20077417af Add files via upload
replacing deleted unitpaylods
2023-04-22 23:47:41 +08:00
Shredmetal
673e00c0e8 Delete unitPayloads.lua
Delete to reuploaded amended unitpayloads
2023-04-22 23:36:36 +08:00
Shredmetal
197159fc2a Add files via upload
Updated aircraftdatabase.ts
2023-04-22 23:33:06 +08:00
Shredmetal
1ca0029407 Delete aircraftdatabase.ts
Delete to reupload amended file
2023-04-22 23:31:07 +08:00
Pax1601
b72d92ffd7 Fixed installer 2023-04-22 10:07:21 +02:00
Pax1601
e04e4b2dec Merge pull request #203 from Pax1601/146-add-in-game-clock-time-to-data-stream
Implemented
2023-04-21 19:10:31 +02:00
Pax1601
35709987e7 Implemented
Added date, start time, elapsed time, current time
2023-04-21 19:10:03 +02:00
Pax1601
bcc6b5b5c3 Merge pull request #202 from Pax1601/200-multiple-errors-referring-to-script
Issue fixed by updating MIST and checking method existance
2023-04-21 19:00:51 +02:00
Pax1601
a047a04d09 Issue fixed by updating MIST and checking method existance 2023-04-21 19:00:29 +02:00
Pax1601
f6d16944c2 Added loadouts 2023-04-21 18:10:09 +02:00
Pax1601
ee361f12f2 Merge pull request #201 from Pax1601/194-atc-tower-assign-altitude
Adding missing files.
2023-04-20 20:20:59 +02:00
PeekabooSteam
14cdec9615 Adding missing files. 2023-04-20 19:14:19 +01:00
Pax1601
5cff54bfde Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-04-20 17:28:49 +02:00
Pax1601
a9e18e42d3 Added missing planes 2023-04-20 17:28:46 +02:00
Pax1601
6ce9b2ddea Merge pull request #199 from Pax1601/feature-atc-tower
Feature atc tower
2023-04-20 15:50:50 +02:00
PeekabooSteam
06f10cd399 Merge pull request #198 from Pax1601/194-atc-tower-assign-altitude
Added assigned speeds, alts, select unit.
2023-04-20 14:23:57 +01:00
PeekabooSteam
3124a0f6b5 Added assigned speeds, alts, select unit. 2023-04-20 14:22:16 +01:00
dpassoni
090973a3d1 Updated version 2023-04-20 12:36:43 +02:00
Pax1601
992b1d40c9 Merge pull request #196 from Pax1601/73-add-tankers-and-awacs-spawning
73 add tankers and awacs spawning
2023-04-20 12:18:57 +02:00
Pax1601
41be6402cd Merge branch 'main' into 73-add-tankers-and-awacs-spawning 2023-04-19 16:35:37 +02:00
Pax1601
c3c84b2115 Follow, tankers and AWACS completed 2023-04-19 16:30:14 +02:00
Pax1601
f24c57cc18 Follow feature completed 2023-04-19 10:19:56 +02:00
Pax1601
cfd98e74ea Added states and more work on custom formations 2023-04-18 11:01:31 +02:00
Pax1601
be69aeb69e Custom formations 2023-04-17 18:01:23 +02:00
PeekabooSteam
79f616cf8d Merge pull request #195 from Pax1601/193-atc-tower-manually-sort-strips
Flights now sortable.
2023-04-16 23:42:04 +01:00
PeekabooSteam
d77735581a Flights now sortable. 2023-04-16 23:34:00 +01:00
Pax1601
77d39c17b8 More work on follow and tanking (added combo tasks) 2023-04-16 20:24:33 +02:00
PeekabooSteam
3eefe441b4 Merge pull request #192 from Pax1601/188-atc-tower-add-plane-to-strip-board-via-click
Can add flights by click.
2023-04-16 13:15:56 +01:00
PeekabooSteam
e84fa7caaa Can add flights by click. 2023-04-16 12:58:14 +01:00
PeekabooSteam
a3d919bad9 Merge pull request #190 from Pax1601/187-atc-tower-list-planes-being-monitored
Flights now listed by board.
2023-04-14 23:13:46 +01:00
PeekabooSteam
8707982769 Flights now listed by board. 2023-04-14 23:11:55 +01:00
Pax1601
39698c66a3 More work on follow and tanking 2023-04-14 17:30:10 +02:00
Pax1601
b56f1ca547 Fixed checkbox and frequency 2023-04-14 07:59:24 +02:00
Pax1601
4a90193426 Added functions to set TACAN and radio frequencies 2023-04-13 08:09:15 +02:00
Pax1601
7eee469bed More work on advanced settings dialog 2023-04-12 17:21:36 +02:00
Pax1601
316261e01e Started to implement advanced settings 2023-04-11 20:30:59 +02:00
Pax1601
df2aef498f Updated version numbers 2023-04-11 20:30:19 +02:00
Pax1601
f4bb484c7d Merge pull request #179 from Pax1601/atc-mission-board
Atc mission board
2023-04-11 15:23:09 +02:00
Pax1601
f4ddbbd1af Merge pull request #184 from Pax1601/180-unit-loadout-overflows-unitinfopanel
String management for loadout items.
2023-04-11 15:22:04 +02:00
Pax1601
c3233ad999 Merge pull request #185 from Pax1601/181-dropdowns-can-overflow-to-window-page
Dropdowns limited to 382px.  Ground unit types are automatically sorted
2023-04-11 15:21:22 +02:00
Pax1601
1f51d69126 Added basic tanker and AWACS enroute tasks
Tanker not working propertly yet, frequency setting still needed
2023-04-11 15:20:17 +02:00
PeekabooSteam
14ae0d083f Dropdowns limited to 382px. Ground unit types are automatically sorted 2023-04-09 15:22:27 +01:00
PeekabooSteam
8d951410e5 String management for loadout items. 2023-04-09 10:49:40 +01:00
PeekabooSteam
7605dd26ff Resolved conflicts 2023-04-09 09:54:21 +01:00
Pax1601
1b093782c3 Merge pull request #182 from Pax1601/176-minus-keystroke-zooms-out-and-brings-up-unit-list
Removed callback at "minus" keypress
2023-04-09 10:12:41 +02:00
Pax1601
2947d55bc5 Merge pull request #183 from Pax1601/163-f-15c-instant-action-cc-bomber-intercept-crashes-olympus
Added check on existance of mist structures
2023-04-09 10:12:29 +02:00
Pax1601
103fcde426 Removed callback at "minus" keypress 2023-04-09 10:11:51 +02:00
Pax1601
3193eb0021 Added check on existance of mist structures 2023-04-09 10:08:49 +02:00
Pax1601
0456bbef52 Minor bugfix on demo data 2023-04-09 09:48:49 +02:00
Pax1601
c54c7d2d78 Merge pull request #174 from Pax1601/147-speed-and-altitude-controls-jumping-back
Sliders no longer jump after update.
2023-04-08 15:16:07 +02:00
Pax1601
9c834e4072 Merge pull request #170 from Pax1601/149-loadout-numbers-overflowing
Aligned numbers within pills.
2023-04-08 15:04:51 +02:00
Pax1601
b10522498b Merge pull request #171 from Pax1601/111-measurebox-shows-000-when-measuring-north-should-read-360
111 measurebox shows 000 when measuring north should read 360
2023-04-08 15:01:44 +02:00
Pax1601
fd23fd3034 Merge pull request #172 from Pax1601/148-missing-scrollbar-for-units-buttons
Added scrollable to selected units' list; bit of tidying up.
2023-04-08 15:00:06 +02:00
Pax1601
3aa6d27ed3 Merge pull request #177 from Pax1601/175-keystrokes-in-input-fields-are-triggering-shortcuts
keyEventWasInInput() function added.
2023-04-08 14:55:36 +02:00
Pax1601
b98c392f79 Merge pull request #178 from Pax1601/121-spawn-context-menu-and-airbase-menu-overflow-window
Clipping is now less bad.
2023-04-08 14:54:15 +02:00
PeekabooSteam
071942b632 Slightly nicer PoC. 2023-04-04 23:38:08 +01:00
PeekabooSteam
5dda45ad22 Clipping is now less bad. 2023-04-04 19:16:00 +01:00
PeekabooSteam
6ffcb76f03 keyEventWasInInput() function added. 2023-04-04 15:51:11 +01:00
PeekabooSteam
6993650ff8 Sliders no longer jump after update. 2023-04-04 15:04:45 +01:00
PeekabooSteam
6b22c1ef63 Added scrollable to selected units' list; bit of tidying up. 2023-03-31 21:06:46 +01:00
PeekabooSteam
ee6fadfb36 Merge branch '111-measurebox-shows-000-when-measuring-north-should-read-360' of https://github.com/Pax1601/DCSOlympus into 111-measurebox-shows-000-when-measuring-north-should-read-360 2023-03-31 20:31:45 +01:00
PeekabooSteam
2f5b9d1f94 360 now shows for bullseyes. 2023-03-31 20:31:36 +01:00
PeekabooSteam
b9f32a5b82 Aligned numbers within pills. 2023-03-31 20:27:04 +01:00
PeekabooSteam
6f64bd1622 ATC Ground board PoC. 2023-03-29 21:15:33 +01:00
Pax1601
ff20eec472 Merge pull request #169 from Pax1601/71-add-counters-to-data-to-avoid-units-jumping-back
Added check on message time
2023-03-29 09:19:53 +02:00
Pax1601
9c9d53f3fb Added check on message time 2023-03-29 09:19:35 +02:00
Pax1601
b4e34bf9e4 Merge pull request #168 from Pax1601/155-pasting-units-generates-many-units-if-ctrl+v-is-held-down
Maximum paste rate set to once every 250ms
2023-03-29 09:00:16 +02:00
Pax1601
73a539bf94 Removed log 2023-03-29 09:00:04 +02:00
Pax1601
ac44c208a8 Maximum paste rate set to once every 250ms 2023-03-29 08:59:32 +02:00
Pax1601
04618cb247 Merge pull request #167 from Pax1601/166-ground-unit-type-not-selected
Fixed
2023-03-29 08:54:20 +02:00
Pax1601
3bdba116e8 Fixed 2023-03-29 08:54:03 +02:00
Pax1601
ea94d8ac24 Merge branch 'main' of https://github.com/Pax1601/DCSOlympus 2023-03-29 08:51:08 +02:00
Pax1601
ab51a76075 Client modified to work on any address 2023-03-29 08:51:05 +02:00
Pax1601
cae9b16d97 Merge pull request #157 from Pax1601/156-delete-lua-function-can-cause-player-desync-in-multiplayer
updated Olympus.delete to avoid player desync
2023-03-28 14:27:28 +02:00
Wirts Legs
ee6537de7c updated Olympus.delete to avoid player desync 2023-03-27 19:16:50 -04:00
Pax1601
efae7c23ff Merge pull request #152 from Pax1601/151-spawn-menu-not-working-in-firefox
PointerEvent changed to MouseEvent.
2023-03-27 09:19:50 +02:00
PeekabooSteam
df79f6577b PointerEvent changed to MouseEvent. 2023-03-26 20:10:25 +01:00
PeekabooSteam
14147168f9 ATC stuff. 2023-03-26 20:00:23 +01:00
PeekabooSteam
da008c220d Added beginnings of new ATC framework. 2023-03-26 15:39:21 +01:00
PeekabooSteam
d86a250575 Remove old ATC code. 2023-03-26 11:00:20 +01:00
WoodyXP
880ce3919d Added emtpy Loadouts for all aircraft 2023-02-14 15:27:35 +01:00
WoodyXP
b489659ddd Merge branch 'main' of https://github.com/WoodyXP/DCSOlympus 2023-02-14 01:39:40 +01:00
WoodyXP
f8344b1662 Added CLSID to payloadNames.js, Updated the payLoadConverter.py so the CLSID can be added, Added 1 custom Loadout in unitPayloads.lue 2023-02-14 01:36:36 +01:00
1511 changed files with 218434 additions and 41702 deletions

46
.github/workflows/build_package.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Build & package
on:
push:
branches: [ "main", "release-candidate" ]
permissions:
contents: read
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
- name: Setup vcpkg
run: |
bootstrap-vcpkg
vcpkg integrate install
- name: Setup Node.js
uses: actions/setup-node@v4
- name: Build
working-directory: .
run: "./build_package.bat"
shell: cmd
- name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.1
with:
name: development_build_not_a_release
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

47
.gitignore vendored
View File

@@ -1,12 +1,45 @@
bin
/scripts/old
.vs
x64
core.user
core.vcxproj.user
*.user
Output
node_modules
/client/TODO.txt
/client/public/javascripts/bundle.js
!client/bin
hgt
/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/latex
/package
/build
/DCS Olympus backups
/zip
*.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,34 @@
GNU GENERAL PUBLIC LICENSE
DCS Olympus
A real-time AI unit control mod for DCS World
Copyright (C) 2023 Veltro & Gang (the "DCS Olympus Team" or the
"Rightsholders")
DCS Olympus (the "MATERIAL" or "Software") is provided completely free
to users subject to the it under both the terms of version 3 of the GNU
General Public License ("GPLv3") as published by the Free Software Foundation,
and the additional terms set out below (the "Additional Terms"). In the event
that the terms of GPLv3 conflict with the Additional Terms, the
Additional Terms shall prevail.
The authors and/or copyright holders of the Software have not received any
financial benefit in connection with the Software. In any event, the
Software is provided “as is”, without warranty of any kind, express or
implied, including but not limited to the warranties of merchantability,
fitness for a particular purpose and non-infringement. In no event shall
the authors and/or copyright holders be liable for any claim, damages or
other liability, whether in an action of contract, tort or otherwise,
arising from, out of or in connection with the Software or the use or
other dealings in the Software.
THIS MATERIAL IS NOT MADE OR SUPPORTED BY EAGLE DYNAMICS SA.
Any party making use of the Software in any manner agrees to be bound by
the entirety of this document.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
@@ -618,57 +648,31 @@ an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
END OF GNU GENERAL PUBLIC LICENCE
How to Apply These Terms to Your New Programs
ADDITIONAL TERMS & CONDITIONS
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
1. Governing Law
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Save where specifically provided for otherwise, the provisions of the
GNU General Public Licence Version 3 above shall be governed by and
interpreted in accordance with English Law and the parties submit to the
exclusive jurisdiction of the English Courts.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
2. Entire Agreement
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The text of this document contains the entire understanding between
you, the licensee, and the authors and/or copyright holders of the
Software with respect to the subject matter to which it pertains.
It supersedes all prior agreements and understandings (if applicable),
oral or written, with respect to such matters.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
3. Unilateral Modification
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
The parties agree that the DCS Olympus Team shall have the right to
unilaterally modify these terms (i.e. the agreement between you and the
DCS Olympus Team for the use of the Software), and that parties shall
be bound by such terms as modified from time to time. The DCS Olympus Team
shall not have an obligation to inform you of such modification, save that
such changes will be published on the DCS Olympus Github Repository located at
https://github.com/Pax1601/DCSOlympus.

103
README.md
View File

@@ -1,40 +1,85 @@
# Important note: DCS Olympus is in alpha state. No official release has been produced yet. The first public version is planned for Q2 2023.
<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)
<img align="left" width="30" src="https://github.com/Pax1601/DCSOlympus/assets/103559271/1c0dd3fd-339c-4b03-94da-3e5215b0358a">
[**YouTube**](https://www.youtube.com/@DCSOlympus)
# DCS Olympus
*A real-time web interface to spawn and control units in DCS World*
![alt text](https://github.com/Pax1601/DCSOlympus/blob/main/client/sample.png?raw=true)
### What is this?
DCS Olympus is a mod for DCS World. It allows users to spawn, control, task, group, and remove units from a DCS World server using a real-time map interface, similarly to Real Time Strategy games. The user interface also provides useful informations units, like loadouts, fuel, tasking, and so on. In the future, more features for DCS World GCI and JTAC will be available.
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.
### Features and how to use it
- Spawn air and ground units, with preset loadouts
- Double click on the map to spawn a blue and red units, both in the air and in the ground, with preset loadouts for air-to-air or air-to-ground tasks;
- Control units
- Select one ore more units to move them around. Hold down ctrl and click to create a route for the unit to follow;
- Attack other units
- After selecting one ore more units, double click on another unit and select "Attack" to attack it, depending on the available weapons.
Additionally Olympus is able to run several effects and unit behaviours beyond the core DCS offerings. This includes such things as napalm and white phosphosous explosions, or setting up AA units to fire at players and miss, and more.
It even includes Red and Blue modes which limit your view and powers to just seeing what your coalition sees, with a spawning budget you could play against your friends even with no-one in the game piloting, or have a Red commander working against a squadron of blue pilots, and/or a blue commander working with them.
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
### 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
### Building DCS Olympus
DCS Olympus is comprised of two modules:
# Frequently Asked Questions
A "core" c++ .dll module, which is run by DCS and exposes all the necessary data, and provides endpoints for commands from a REST server. A Visual Studio 2017/2019/2022 solution is provided, and requires no additional configuration. The core dll solution has two dependencies, both can be installed using vcpkg (https://vcpkg.io/en/getting-started.html):
- cpprestsdk: `vcpkg install cpprestsdk:x64-windows`
- geographiclib: `vcpkg install geographiclib:x64-windows`
A "client" node.js typescript web app, which can be hosted on the server using express.js. A Visual Studio Code configuration is provided for debugging. The client requires node.js to be installed for building (https://nodejs.org/en/). After installing node.js, move in the client folder and run the following commands:
- `npm install`
- `npm -g install`
After installing all the necessary dependencies you can start a development server executing the *client/debug.bat* batch file, and visiting http:\\localhost:3000 with any modern browser (tested with updated Chrome, Firefox and Edge). However, it is highly suggested to simply run the `Launch Chrome against localhost` debug configuration in Visual Studio Code.
### 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/Setup-Troubleshooting) for common issues and solutions.
Read through the [Olympus User Guide](https://github.com/Pax1601/DCSOlympus/wiki/2.-User-Guide) to learn how to use Olympus.
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? ###
Same as above!
### Do you have a roadmap? ###
We do not have a roadmap no, we have a laundry list of things we are hoping to do.
These include but are not limited to:
1) Enhancements to helicopter play
2) More features around use of ground units
3) More unique effects and behaviours
4) ATC/AIC features
5) Usability features like unit painters etc
However we cannot commit to specific features, feature release order, or timelines, please remember this isn't our job and we work on it in our free time because we love DCS
### Does Olympus support mods? ###
Generally OIympus will not have any issues with other mods, however you may need to tell olympus about modded units in order to be able to dynamically spawn them etc
Keep in mind that any mods you do choose to spawn your players will need to have, some mod unit just appear as a su27 or leo2 etc. When a player is missing them, others can cause client crashes. So be smart about how you use them.
### Is Olympus compatible with mission scripts? ###
We have tried hard to keep Olympus from interfering with other scripts, we have tested with a variety of new and old mission scripts and generally expect it will not be an issue.
However we cannot foresee everything people come up with so we suggest testing with what you have in mind once olympus releases
### How does it work? ###
The quick answer is magic.
The long answer is well all the code is there for you to read.
The middle answer is a bit like SRS does. Olympus consists of two parts.
(A) Olympus back end: A dll, run by DCS, that sends data out and gets commands in via a REST API;
(B) Webserver exe: The one you start when starting the server via the desktop shortcut.
A and B never communicate when you connect the client you download the web page and some other minor stuff from B, and you get the DCS data from and send commands to A.
### How much does Olympus impact performance? ###
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

12
backend/DCSOlympus.props Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>true</VcpkgEnableManifest>
<VcpkgAutoLink>true</VcpkgAutoLink>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />
</Project>

110
backend/core/core.rc Normal file
View File

@@ -0,0 +1,110 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Italian (Italy) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Italian (Italy) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "core.dll"
VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "core.dll"
VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "2.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -36,7 +36,7 @@
<ClInclude Include="include\aircraft.h" />
<ClInclude Include="include\airunit.h" />
<ClInclude Include="include\commands.h" />
<ClInclude Include="include\measure.h" />
<ClInclude Include="include\datatypes.h" />
<ClInclude Include="include\groundunit.h" />
<ClInclude Include="include\helicopter.h" />
<ClInclude Include="include\navyunit.h" />
@@ -46,13 +46,15 @@
<ClInclude Include="include\unit.h" />
<ClInclude Include="include\unitsmanager.h" />
<ClInclude Include="include\weapon.h" />
<ClInclude Include="include\weaponsmanager.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\aircraft.cpp" />
<ClCompile Include="src\airunit.cpp" />
<ClCompile Include="src\commands.cpp" />
<ClCompile Include="src\core.cpp" />
<ClCompile Include="src\measure.cpp" />
<ClCompile Include="src\datatypes.cpp" />
<ClCompile Include="src\groundunit.cpp" />
<ClCompile Include="src\helicopter.cpp" />
<ClCompile Include="src\navyunit.cpp" />
@@ -62,6 +64,10 @@
<ClCompile Include="src\unit.cpp" />
<ClCompile Include="src\unitsmanager.cpp" />
<ClCompile Include="src\weapon.cpp" />
<ClCompile Include="src\weaponsmanager.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="core.rc" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
@@ -104,22 +110,26 @@
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir>
<OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -172,6 +182,7 @@
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>lua.lib; GeographicLib-i.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -185,7 +196,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>
</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>include;..\..\third-party\lua\include;..\utils\include;..\shared\include;..\dcstools\include;..\logger\include;..\luatools\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>include;..\..\third-party\base64\include;..\..\third-party\lua\include;..\utils\include;..\shared\include;..\dcstools\include;..\logger\include;..\luatools\include</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>

View File

@@ -45,9 +45,13 @@
<ClInclude Include="include\weapon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\measure.h">
<ClInclude Include="include\datatypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\weaponsmanager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\aircraft.cpp">
@@ -89,8 +93,14 @@
<ClCompile Include="src\weapon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\measure.cpp">
<ClCompile Include="src\datatypes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\weaponsmanager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="core.rc" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,20 @@
#pragma once
#include "airunit.h"
#define AIRCRAFT_DEST_DIST_THR 2000 // Meters
class Aircraft : public AirUnit
{
public:
Aircraft(json::value json, unsigned int ID);
static void loadDatabase(string path);
virtual void changeSpeed(string change);
virtual void changeAltitude(string change);
virtual double getDestinationReachedThreshold() { return AIRCRAFT_DEST_DIST_THR; }
protected:
static json::value database;
};

View File

@@ -0,0 +1,28 @@
#pragma once
#include "framework.h"
#include "utils.h"
#include "dcstools.h"
#include "luatools.h"
#include "Unit.h"
#define AIR_DEST_DIST_THR 2000 // Meters
class AirUnit : public Unit
{
public:
AirUnit(json::value json, unsigned int ID);
virtual void setDefaults(bool force = false);
virtual void setState(unsigned char newState);
virtual void changeSpeed(string change) = 0;
virtual void changeAltitude(string change) = 0;
virtual double getDestinationReachedThreshold() { return AIR_DEST_DIST_THR; }
virtual void setRacetrackLength(double newValue);
virtual void setRacetrackAnchor(Coords newValue);
virtual void setRacetrackBearing(double newValue);
protected:
virtual void AIloop();
};

View File

@@ -0,0 +1,536 @@
#pragma once
#include "framework.h"
#include "luatools.h"
#include "utils.h"
#include "logger.h"
#include "datatypes.h"
namespace CommandPriority {
enum CommandPriorities { LOW, MEDIUM, HIGH, IMMEDIATE };
};
namespace SetCommandType {
enum SetCommandTypes {
ROE = 0,
REACTION_ON_THREAT = 1,
RADAR_USING = 3,
FLARE_USING = 4,
FORMATION = 5,
RTB_ON_BINGO = 6,
SILENCE = 7,
ALARM_STATE = 9,
RTB_ON_OUT_OF_AMMO = 10,
ECM_USING = 13,
PROHIBIT_AA = 14,
PROHIBIT_JETT = 15,
PROHIBIT_AB = 16,
PROHIBIT_AG = 17,
MISSILE_ATTACK = 18,
PROHIBIT_WP_PASS_REPORT = 19,
ENGAGE_AIR_WEAPONS = 20,
OPTION_RADIO_USAGE_CONTACT = 21,
OPTION_RADIO_USAGE_ENGAGE = 22,
OPTION_RADIO_USAGE_KILL = 23,
JETT_TANKS_IF_EMPTY = 25,
FORCED_ATTACK = 26
};
}
namespace ROE {
enum ROEs {
WEAPON_FREE = 0,
OPEN_FIRE_WEAPON_FREE = 1,
OPEN_FIRE = 2,
RETURN_FIRE = 3,
WEAPON_HOLD = 4,
};
}
namespace AlarmState {
enum AlarmStates {
AUTO = 0,
GREEN = 1,
RED = 2,
};
}
namespace ReactionToThreat {
enum ReactionsToThreat {
NO_REACTION = 0,
PASSIVE_DEFENCE = 1,
EVADE_FIRE = 2,
BYPASS_AND_ESCAPE = 3,
ALLOW_ABORT_MISSION = 4
};
}
namespace EmissionCountermeasure {
enum ReactionsToThreat {
SILENT = 0,
ATTACK = 1,
DEFEND = 2,
FREE = 3
};
}
namespace RadarUse {
enum RadarUses {
NEVER = 0,
FOR_ATTACK_ONLY = 1,
FOR_SEARCH_IF_REQUIRED = 2,
FOR_CONTINUOUS_SEARCH = 3
};
}
namespace FlareUse {
enum FlareUses {
NEVER = 0,
AGAINST_FIRED_MISSILE = 1,
WHEN_FLYING_IN_SAM_WEZ = 2,
WHEN_FLYING_NEAR_ENEMIES = 3
};
}
namespace ECMUse {
enum ECMUses {
NEVER_USE = 0,
USE_IF_ONLY_LOCK_BY_RADAR = 1,
USE_IF_DETECTED_LOCK_BY_RADAR = 2,
ALWAYS_USE = 3
};
}
/* Base command class */
class Command
{
public:
Command(function<void(void)> callback) : callback(callback) {};
unsigned int getPriority() { return priority; }
virtual string getString() = 0;
virtual unsigned int getLoad() = 0;
const string getHash() { return hash; }
void executeCallback() { callback(); }
protected:
unsigned int priority = CommandPriority::LOW;
const string hash = random_string(16);
function<void(void)> callback;
};
/* Simple low priority move command (from user click) */
class Move : public Command
{
public:
Move(string groupName, Coords destination, double speed, string speedType, double altitude,
string altitudeType, string taskOptions, string category, bool onRoad, function<void(void)> callback = []() {}) :
Command(callback),
groupName(groupName),
destination(destination),
speed(speed),
speedType(speedType),
altitude(altitude),
altitudeType(altitudeType),
taskOptions(taskOptions),
category(category),
onRoad(onRoad)
{
priority = CommandPriority::MEDIUM;
};
virtual string getString();
virtual unsigned int getLoad() { return onRoad? 45: 5; }
private:
const string groupName;
const Coords destination;
const double speed;
const string speedType;
const double altitude;
const string altitudeType;
const string taskOptions;
const string category;
const bool onRoad;
};
/* Smoke command */
class Smoke : public Command
{
public:
Smoke(string color, Coords location, function<void(void)> callback = [](){}) :
Command(callback),
color(color),
location(location)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 2; }
private:
const string color;
const Coords location;
};
/* Spawn ground unit command */
class SpawnGroundUnits : public Command
{
public:
SpawnGroundUnits(string coalition, vector<SpawnOptions> spawnOptions, string country, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
coalition(coalition),
spawnOptions(spawnOptions),
country(country),
immediate(immediate)
{
priority = immediate? CommandPriority::IMMEDIATE: CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return immediate? 5: 30; }
private:
const string coalition;
const vector<SpawnOptions> spawnOptions;
const string country;
const bool immediate;
};
/* Spawn navy unit command */
class SpawnNavyUnits : public Command
{
public:
SpawnNavyUnits(string coalition, vector<SpawnOptions> spawnOptions, string country, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
coalition(coalition),
spawnOptions(spawnOptions),
country(country),
immediate(immediate)
{
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return immediate ? 5 : 60; }
private:
const string coalition;
const vector<SpawnOptions> spawnOptions;
const string country;
const bool immediate;
};
/* Spawn aircraft command */
class SpawnAircrafts : public Command
{
public:
SpawnAircrafts(string coalition, vector<SpawnOptions> spawnOptions, string airbaseName, string country, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
coalition(coalition),
spawnOptions(spawnOptions),
airbaseName(airbaseName),
country(country),
immediate(immediate)
{
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return immediate ? 5 : 45; }
private:
const string coalition;
const vector<SpawnOptions> spawnOptions;
const string airbaseName;
const string country;
const bool immediate;
};
/* Spawn helicopter command */
class SpawnHelicopters : public Command
{
public:
SpawnHelicopters(string coalition, vector<SpawnOptions> spawnOptions, string airbaseName, string country, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
coalition(coalition),
spawnOptions(spawnOptions),
airbaseName(airbaseName),
country(country),
immediate(immediate)
{
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return immediate ? 5 : 45; }
private:
const string coalition;
const vector<SpawnOptions> spawnOptions;
const string airbaseName;
const string country;
const bool immediate;
};
/* Clone unit command */
class Clone : public Command
{
public:
Clone(vector<CloneOptions> cloneOptions, bool deleteOriginal, function<void(void)> callback = [](){}) :
Command(callback),
cloneOptions(cloneOptions),
deleteOriginal(deleteOriginal)
{
priority = CommandPriority::LOW;
};
virtual string getString();
virtual unsigned int getLoad() { return 30; }
private:
const vector<CloneOptions> cloneOptions;
const bool deleteOriginal;
};
/* Delete unit command */
class Delete : public Command
{
public:
Delete(unsigned int ID, bool explosion, string explosionType, bool immediate, function<void(void)> callback = [](){}) :
Command(callback),
ID(ID),
explosion(explosion),
explosionType(explosionType),
immediate(immediate)
{
priority = CommandPriority::HIGH;
immediate = immediate;
};
virtual string getString();
virtual unsigned int getLoad() { return immediate? 1: 30; }
private:
const unsigned int ID;
const bool explosion;
const string explosionType;
const bool immediate;
};
/* SetTask command */
class SetTask : public Command
{
public:
SetTask(string groupName, string task, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
task(task)
{
priority = CommandPriority::MEDIUM;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const string groupName;
const string task;
};
/* Reset task command */
class ResetTask : public Command
{
public:
ResetTask(string groupName, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName)
{
priority = CommandPriority::HIGH;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const string groupName;
};
/* Set command */
class SetCommand : public Command
{
public:
SetCommand(string groupName, string command, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
command(command)
{
priority = CommandPriority::HIGH;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const string groupName;
const string command;
};
/* Set option command */
class SetOption : public Command
{
public:
SetOption(string groupName, unsigned int optionID, unsigned int optionValue, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
optionID(optionID),
optionValue(optionValue),
optionBool(false),
isBoolean(false)
{
priority = CommandPriority::HIGH;
};
SetOption(string groupName, unsigned int optionID, bool optionBool, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
optionID(optionID),
optionValue(0),
optionBool(optionBool),
isBoolean(true)
{
priority = CommandPriority::HIGH;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const string groupName;
const unsigned int optionID;
const unsigned int optionValue;
const bool optionBool;
const bool isBoolean;
};
/* Set on off */
class SetOnOff : public Command
{
public:
SetOnOff(string groupName, bool onOff, function<void(void)> callback = [](){}) :
Command(callback),
groupName(groupName),
onOff(onOff)
{
priority = CommandPriority::HIGH;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const string groupName;
const bool onOff;
};
/* Make a ground explosion */
class Explosion : public Command
{
public:
Explosion(unsigned int intensity, string explosionType, Coords location, function<void(void)> callback = [](){}) :
Command(callback),
location(location),
intensity(intensity),
explosionType(explosionType)
{
priority = CommandPriority::MEDIUM;
};
virtual string getString();
virtual unsigned int getLoad() { return 5; }
private:
const Coords location;
const unsigned int intensity;
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;
};

View File

@@ -0,0 +1,183 @@
#pragma once
#include "framework.h"
#include "utils.h"
namespace DataIndex {
enum DataIndexes {
startOfData = 0,
category,
alive,
alarmState,
radarState,
human,
controlled,
coalition,
country,
name,
unitName,
callsign,
unitID,
groupID,
groupName,
state,
task,
hasTask,
position,
speed,
horizontalVelocity,
verticalVelocity,
heading,
track,
isActiveTanker,
isActiveAWACS,
onOff,
followRoads,
fuel,
desiredSpeed,
desiredSpeedType,
desiredAltitude,
desiredAltitudeType,
leaderID,
formationOffset,
targetID,
targetPosition,
ROE,
reactionToThreat,
emissionsCountermeasures,
TACAN,
radio,
generalSettings,
ammo,
contacts,
activePath,
isLeader,
operateAs,
shotsScatter,
shotsIntensity,
health,
racetrackLength,
racetrackAnchor,
racetrackBearing,
timeToNextTasking,
barrelHeight,
muzzleVelocity,
aimTime,
shotsToFire,
shotsBaseInterval,
shotsBaseScatter,
engagementRange,
targetingRange,
aimMethodRange,
acquisitionRange,
airborne,
lastIndex,
endOfData = 255
};
}
namespace State
{
enum States
{
NONE = 0,
IDLE,
REACH_DESTINATION,
ATTACK,
FOLLOW,
LAND,
REFUEL,
AWACS,
TANKER,
BOMB_POINT,
CARPET_BOMB,
BOMB_BUILDING,
FIRE_AT_AREA,
SIMULATE_FIRE_FIGHT,
SCENIC_AAA,
MISS_ON_PURPOSE,
LAND_AT_POINT
};
};
namespace ShotsScatter
{
enum ShotsScatters
{
NONE = 0,
HIGH,
MEDIUM,
LOW
};
};
namespace ShotsIntensity
{
enum ShotsIntensities
{
NONE = 0,
LOW,
MEDIUM,
HIGH
};
};
#pragma pack(push, 1)
namespace DataTypes {
struct TACAN
{
bool isOn = false;
unsigned char channel = 40;
char XY = 'X';
char callsign[4];
};
struct Radio
{
unsigned int frequency = 124000000; // MHz
unsigned char callsign = 1;
unsigned char callsignNumber = 1;
};
struct GeneralSettings
{
bool prohibitJettison = false;
bool prohibitAA = false;
bool prohibitAG = false;
bool prohibitAfterburner = false;
bool prohibitAirWpn = false;
};
struct Ammo {
unsigned short quantity = 0;
char name[33];
unsigned char guidance = 0;
unsigned char category = 0;
unsigned char missileCategory = 0;
};
struct Contact {
unsigned int ID = 0;
unsigned char detectionMethod = 0;
};
}
#pragma pack(pop)
bool operator==(const DataTypes::TACAN& lhs, const DataTypes::TACAN& rhs);
bool operator==(const DataTypes::Radio& lhs, const DataTypes::Radio& 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::Contact& lhs, const DataTypes::Contact& rhs);
struct SpawnOptions {
string unitType;
Coords location;
string loadout;
string skill;
string liveryID;
double heading;
};
struct CloneOptions {
unsigned int ID;
Coords location;
};

View File

@@ -0,0 +1,25 @@
#pragma once
#include "unit.h"
#define GROUND_DEST_DIST_THR 10
class GroundUnit : public Unit
{
public:
GroundUnit(json::value json, unsigned int ID);
static void loadDatabase(string path);
virtual void setState(unsigned char newState);
virtual void setDefaults(bool force = false);
virtual void changeSpeed(string change);
virtual void setOnOff(bool newOnOff, bool force = false);
virtual void setFollowRoads(bool newFollowRoads, bool force = false);
string aimAtPoint(Coords aimTarget);
protected:
virtual void AIloop();
static json::value database;
};

View File

@@ -0,0 +1,20 @@
#pragma once
#include "airunit.h"
#define HELICOPTER_DEST_DIST_THR 500 // Meters
class Helicopter : public AirUnit
{
public:
Helicopter(json::value json, unsigned int ID);
static void loadDatabase(string path);
virtual void changeSpeed(string change);
virtual void changeAltitude(string change);
virtual double getDestinationReachedThreshold() { return HELICOPTER_DEST_DIST_THR; }
protected:
static json::value database;
};

View File

@@ -0,0 +1,22 @@
#pragma once
#include "unit.h"
#define NAVY_DEST_DIST_THR 100
class NavyUnit : public Unit
{
public:
NavyUnit(json::value json, unsigned int ID);
static void loadDatabase(string path);
virtual void setState(unsigned char newState);
virtual void setDefaults(bool force = false);
virtual void changeSpeed(string change);
virtual void setOnOff(bool newOnOff, bool force = false);
protected:
virtual void AIloop();
static json::value database;
};

View File

@@ -0,0 +1,50 @@
#pragma once
#include "framework.h"
#include "luatools.h"
#include "commands.h"
class Scheduler
{
public:
Scheduler(lua_State* L);
~Scheduler();
void appendCommand(Command* command);
void execute(lua_State* L);
void handleRequest(string key, json::value value, string username, json::value& answer);
bool checkSpawnPoints(int spawnPoints, string coalition);
bool isCommandExecuted(string commandHash) { return (find(executedCommandsHashes.begin(), executedCommandsHashes.end(), commandHash) != executedCommandsHashes.end()); }
void setFrameRate(double newFrameRate) { frameRate = newFrameRate; }
void setRestrictSpawns(bool newRestrictSpawns) { restrictSpawns = newRestrictSpawns; }
void setRestrictToCoalition(bool newRestrictToCoalition) { restrictToCoalition = newRestrictToCoalition; }
void setSetupTime(unsigned int newSetupTime) { setupTime = newSetupTime; }
void setBlueSpawnPoints(int newBlueSpawnPoints) { blueSpawnPoints = newBlueSpawnPoints; }
void setRedSpawnPoints(int newRedSpawnPoints) { redSpawnPoints = newRedSpawnPoints; }
void setEras(vector<string> newEras) { eras = newEras; }
void setCommandModeOptions(json::value newOptions);
int getFrameRate() { return static_cast<int>(round(frameRate)); };
int getLoad();
bool getRestrictSpawns() { return restrictSpawns; }
bool getRestrictToCoalition() { return restrictToCoalition; }
unsigned int getSetupTime() { return setupTime; }
int getBlueSpawnPoints() { return blueSpawnPoints; }
int getRedSpawnPoints() { return redSpawnPoints; }
vector<string> getEras() { return eras; }
json::value getCommandModeOptions();
private:
list<Command*> commands;
list<string> executedCommandsHashes;
unsigned int load = 0;
double frameRate = 0;
bool restrictSpawns = false;
bool restrictToCoalition = false;
unsigned int setupTime = 300;
int blueSpawnPoints = 10000;
int redSpawnPoints = 10000;
vector<string> eras = { "WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern" };
};

View File

@@ -5,7 +5,11 @@
function Olympus.protectedCall(...)\n\n \
local status, retval = pcall(...)\n \
if not status then\n \
trigger.action.outText(\"ERROR: \" ..retval, 20)\n \
if Olympus.log ~= nil then\n \
Olympus.log:error(retval)\n \
else\n \
trigger.action.outText(\"Olympus critical error: \" ..retval, 20)\n \
end\n \
end\n \
end\n \
trigger.action.outText(\"Olympus.protectedCall registered successfully\", 10)\n"

View File

@@ -24,8 +24,17 @@ private:
void handle_request(http_request request, function<void(json::value const&, json::value&)> action);
void handle_put(http_request request);
string extractUsername(http_request& request);
string extractPassword(http_request& request);
void task();
atomic<bool> runListener;
string gameMasterPassword = "";
string blueCommanderPassword = "";
string redCommanderPassword = "";
string atcPassword = "";
string observerPassword = "";
};

330
backend/core/include/unit.h Normal file
View File

@@ -0,0 +1,330 @@
#pragma once
#include "framework.h"
#include "utils.h"
#include "dcstools.h"
#include "luatools.h"
#include "logger.h"
#include "commands.h"
#include "datatypes.h"
#include <chrono>
using namespace std::chrono;
#define TASK_CHECK_INIT_VALUE 10
class Unit
{
public:
Unit(json::value json, unsigned int ID);
~Unit();
/********** Methods **********/
virtual void initialize(json::value json) final;
virtual void setDefaults(bool force = false);
void runAILoop();
virtual void update(json::value json, double dt) final;
void refreshLeaderData(unsigned long long time);
unsigned int getID() { return ID; }
void getData(stringstream& ss, unsigned long long time);
Coords getActiveDestination() { return activeDestination; }
virtual void changeSpeed(string change) {};
virtual void changeAltitude(string change) {};
bool setActiveDestination();
void resetActiveDestination();
void landAt(Coords loc);
bool updateActivePath(bool looping);
void clearActivePath();
void pushActivePathFront(Coords newActivePathFront);
void pushActivePathBack(Coords newActivePathBack);
void popActivePathFront();
void goToDestination(string enrouteTask = "nil");
bool isDestinationReached(double threshold);
string getTargetName();
string getLeaderName();
bool isTargetAlive();
bool isLeaderAlive();
void resetTask();
bool checkTaskFailed();
void resetTaskFailedCounter();
void setHasTaskAssigned(bool newHasTaskAssigned);
void setEnableTaskCheckFailed(bool newEnableTaskCheckFailed) { enableTaskFailedCheck = newEnableTaskCheckFailed; }
bool getEnableTaskCheckFailed() { return enableTaskFailedCheck; }
void triggerUpdate(unsigned char datumIndex);
bool hasFreshData(unsigned long long time);
bool checkFreshness(unsigned char datumIndex, unsigned long long time);
unsigned int computeTotalAmmo();
/********** Setters **********/
virtual void setCategory(string newValue) { updateValue(category, newValue, DataIndex::category); }
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 setControlled(bool newValue) { updateValue(controlled, newValue, DataIndex::controlled); }
virtual void setCoalition(unsigned char newValue) { updateValue(coalition, newValue, DataIndex::coalition); }
virtual void setCountry(unsigned char newValue) { updateValue(country, newValue, DataIndex::country); }
virtual void setName(string newValue) { updateValue(name, newValue, DataIndex::name); }
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 setState(unsigned char newValue) { updateValue(state, newValue, DataIndex::state); };
virtual void setTask(string newValue) { updateValue(task, newValue, DataIndex::task); }
virtual void setHasTask(bool newValue);
virtual void setPosition(Coords newValue) { updateValue(position, newValue, DataIndex::position); }
virtual void setSpeed(double newValue) { updateValue(speed, newValue, DataIndex::speed); }
virtual void setHorizontalVelocity(double newValue) { updateValue(horizontalVelocity, newValue, DataIndex::horizontalVelocity); }
virtual void setVerticalVelocity(double newValue) { updateValue(verticalVelocity, newValue, DataIndex::verticalVelocity); }
virtual void setHeading(double newValue) { updateValue(heading, newValue, DataIndex::heading); }
virtual void setTrack(double newValue) { updateValue(track, newValue, DataIndex::track); }
virtual void setIsActiveTanker(bool newValue);
virtual void setIsActiveAWACS(bool newValue);
virtual void setOnOff(bool newValue, bool force = false) { updateValue(onOff, newValue, DataIndex::onOff); };
virtual void setFollowRoads(bool newValue, bool force = false) { updateValue(followRoads, newValue, DataIndex::followRoads); };
virtual void setFuel(unsigned short newValue) { updateValue(fuel, newValue, DataIndex::fuel); }
virtual void setDesiredSpeed(double newValue);
virtual void setDesiredSpeedType(string newValue);
virtual void setDesiredAltitude(double newValue);
virtual void setDesiredAltitudeType(string newValue);
virtual void setLeaderID(unsigned int newValue) { updateValue(leaderID, newValue, DataIndex::leaderID); }
virtual void setFormationOffset(Offset formationOffset);
virtual void setTargetID(unsigned int newValue) { updateValue(targetID, newValue, DataIndex::targetID); }
virtual void setTargetPosition(Coords newValue) { updateValue(targetPosition, newValue, DataIndex::targetPosition); }
virtual void setROE(unsigned char newValue, bool force = false);
virtual void setReactionToThreat(unsigned char newValue, bool force = false);
virtual void setEmissionsCountermeasures(unsigned char newValue, bool force = false);
virtual void setTACAN(DataTypes::TACAN newValue, bool force = false);
virtual void setRadio(DataTypes::Radio newValue, bool force = false);
virtual void setGeneralSettings(DataTypes::GeneralSettings newValue, bool force = false);
virtual void setAmmo(vector<DataTypes::Ammo> newValue);
virtual void setContacts(vector<DataTypes::Contact> newValue);
virtual void setActivePath(list<Coords> newValue);
virtual void setIsLeader(bool newValue) { updateValue(isLeader, newValue, DataIndex::isLeader); }
virtual void setOperateAs(unsigned char newValue) { updateValue(operateAs, newValue, DataIndex::operateAs); }
virtual void setShotsScatter(unsigned char newValue) { updateValue(shotsScatter, newValue, DataIndex::shotsScatter); }
virtual void setShotsIntensity(unsigned char newValue) { updateValue(shotsIntensity, newValue, DataIndex::shotsIntensity); }
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); }
/********** Getters **********/
virtual string getCategory() { return category; };
virtual bool getAlive() { return alive; }
virtual unsigned char getAlarmState() { return alarmState; }
virtual bool getHuman() { return human; }
virtual bool getControlled() { return controlled; }
virtual unsigned char getCoalition() { return coalition; }
virtual unsigned char getCountry() { return country; }
virtual string getName() { return name; }
virtual string getCallsign() { return callsign; }
virtual string getUnitName() { return unitName; }
virtual string getGroupName() { return groupName; }
virtual unsigned int getUnitID() { return unitID; }
virtual unsigned int getGroupID() { return groupID; }
virtual unsigned char getState() { return state; }
virtual string getTask() { return task; }
virtual bool getHasTask() { return hasTask; }
virtual Coords getPosition() { return position; }
virtual double getSpeed() { return speed; }
virtual double getHorizontalVelocity() { return horizontalVelocity; }
virtual double getVerticalVelocity() { return verticalVelocity; }
virtual double getHeading() { return heading; }
virtual double getTrack() { return track; }
virtual bool getIsActiveTanker() { return isActiveTanker; }
virtual bool getIsActiveAWACS() { return isActiveAWACS; }
virtual bool getOnOff() { return onOff; };
virtual bool getFollowRoads() { return followRoads; };
virtual unsigned short getFuel() { return fuel; }
virtual double getDesiredSpeed() { return desiredSpeed; };
virtual bool getDesiredSpeedType() { return desiredSpeedType; };
virtual double getDesiredAltitude() { return desiredAltitude; };
virtual bool getDesiredAltitudeType() { return desiredAltitudeType; };
virtual unsigned int getLeaderID() { return leaderID; }
virtual Offset getFormationOffset() { return formationOffset; }
virtual unsigned int getTargetID() { return targetID; }
virtual Coords getTargetPosition() { return targetPosition; }
virtual unsigned char getROE() { return ROE; }
virtual unsigned char getReactionToThreat() { return reactionToThreat; }
virtual unsigned char getEmissionsCountermeasures() { return emissionsCountermeasures; };
virtual DataTypes::TACAN getTACAN() { return TACAN; }
virtual DataTypes::Radio getRadio() { return radio; }
virtual DataTypes::GeneralSettings getGeneralSettings() { return generalSettings; }
virtual vector<DataTypes::Ammo> getAmmo() { return ammo; }
virtual vector<DataTypes::Contact> getContacts() { return contacts; }
virtual list<Coords> getActivePath() { return activePath; }
virtual bool getIsLeader() { return isLeader; }
virtual unsigned char getOperateAs() { return operateAs; }
virtual unsigned char getShotsScatter() { return shotsScatter; }
virtual unsigned char getShotsIntensity() { return shotsIntensity; }
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; }
protected:
unsigned int ID;
string category;
bool alive = false;
bool human = false;
bool controlled = false;
unsigned char coalition = NULL;
unsigned char country = NULL;
string name = "";
string unitName = "";
string callsign = "";
unsigned int unitID = NULL;
unsigned int groupID = NULL;
string groupName = "";
unsigned char state = State::NONE;
unsigned char alarmState = AlarmState::AUTO;
bool radarState = false;
string task = "";
bool hasTask = false;
Coords position = Coords(NULL);
double speed = NULL;
double horizontalVelocity = NULL;
double verticalVelocity = NULL;
double heading = NULL;
double track = NULL;
bool isActiveTanker = false;
bool isActiveAWACS = false;
bool onOff = true;
bool followRoads = false;
unsigned short fuel = 0;
double desiredSpeed = 0;
bool desiredSpeedType = 0; /* CAS */
double desiredAltitude = 1;
bool desiredAltitudeType = 0; /* ASL */
unsigned int leaderID = NULL;
double racetrackLength = NULL;
Coords racetrackAnchor = Coords(NULL);
double racetrackBearing = NULL;
Offset formationOffset = Offset(NULL);
unsigned int targetID = NULL;
Coords targetPosition = Coords(NULL);
unsigned char ROE = ROE::OPEN_FIRE_WEAPON_FREE;
unsigned char reactionToThreat = ReactionToThreat::EVADE_FIRE;
unsigned char emissionsCountermeasures = EmissionCountermeasure::DEFEND;
DataTypes::TACAN TACAN;
DataTypes::Radio radio;
DataTypes::GeneralSettings generalSettings;
vector<DataTypes::Ammo> ammo;
vector<DataTypes::Contact> contacts;
list<Coords> activePath;
bool isLeader = false;
unsigned char operateAs = 2;
Coords activeDestination = Coords(NULL);
unsigned char shotsScatter = 2;
unsigned char shotsIntensity = 2;
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;
/********** Other **********/
unsigned int taskCheckCounter = 0;
Unit* missOnPurposeTarget = nullptr;
bool hasTaskAssigned = false;
double initialFuel = 0;
map<unsigned char, unsigned long long> updateTimeMap;
unsigned long long lastLoopTime = 0;
bool enableTaskFailedCheck = false;
unsigned long nextTaskingMilliseconds = 0;
unsigned int totalShellsFired = 0;
unsigned int shellsFiredAtTasking = 0;
unsigned int oldAmmo = 0;
/********** Private methods **********/
virtual void AIloop() = 0;
void appendString(stringstream& ss, const unsigned char& datumIndex, const string& datumValue) {
const unsigned short size = static_cast<unsigned short>(datumValue.size());
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&size, sizeof(unsigned short));
ss << datumValue;
}
/********** Template methods **********/
template <typename T>
void updateValue(T& value, T& newValue, unsigned char datumIndex)
{
if (newValue != value)
{
triggerUpdate(datumIndex);
value = newValue;
}
}
template <typename T>
void appendNumeric(stringstream& ss, const unsigned char& datumIndex, T& datumValue) {
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&datumValue, sizeof(T));
}
template <typename T>
void appendVector(stringstream& ss, const unsigned char& datumIndex, vector<T>& datumValue) {
const unsigned short size = static_cast<unsigned short>(datumValue.size());
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&size, sizeof(unsigned short));
for (auto& el : datumValue)
ss.write((const char*)&el, sizeof(T));
}
template <typename T>
void appendList(stringstream& ss, const unsigned char& datumIndex, list<T>& datumValue) {
const unsigned short size = static_cast<unsigned short>(datumValue.size());;
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&size, sizeof(unsigned short));
for (auto& el: datumValue)
ss.write((const char*)&el, sizeof(T));
}
};

View File

@@ -0,0 +1,34 @@
#pragma once
#include "framework.h"
#include "dcstools.h"
class Unit;
class UnitsManager
{
public:
UnitsManager(lua_State* L);
~UnitsManager();
map<unsigned int, Unit*>& getUnits() { return units; };
Unit* getUnit(unsigned int ID);
bool isUnitInGroup(Unit* unit);
bool isUnitGroupLeader(Unit* unit, Unit*& leader);
Unit* getGroupLeader(unsigned int ID);
Unit* getGroupLeader(Unit* unit);
vector<Unit*> getGroupMembers(string groupName);
void update(json::value& missionData, double dt);
void runAILoop();
void getUnitData(stringstream &ss, unsigned long long time);
void deleteUnit(unsigned int ID, bool explosion, string explosionType, bool immediate);
void acquireControl(unsigned int ID);
void loadDatabases();
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, bool airborneOnly = true);
private:
map<unsigned int, Unit*> units;
json::value missionDB;
};

View File

@@ -0,0 +1,122 @@
#pragma once
#include "framework.h"
#include "utils.h"
#include "dcstools.h"
#include "luatools.h"
#include "logger.h"
#include "commands.h"
#include "datatypes.h"
#include <chrono>
using namespace std::chrono;
class Weapon
{
public:
Weapon(json::value json, unsigned int ID);
~Weapon();
/********** Methods **********/
void initialize(json::value json);
void update(json::value json, double dt);
unsigned int getID() { return ID; }
void getData(stringstream& ss, unsigned long long time);
void triggerUpdate(unsigned char datumIndex);
bool hasFreshData(unsigned long long time);
bool checkFreshness(unsigned char datumIndex, unsigned long long time);
/********** Setters **********/
virtual void setCategory(string newValue) { updateValue(category, newValue, DataIndex::category); }
virtual void setAlive(bool newValue) { updateValue(alive, newValue, DataIndex::alive); }
virtual void setCoalition(unsigned char newValue) { updateValue(coalition, newValue, DataIndex::coalition); }
virtual void setName(string newValue) { updateValue(name, newValue, DataIndex::name); }
virtual void setPosition(Coords newValue) { updateValue(position, newValue, DataIndex::position); }
virtual void setSpeed(double newValue) { updateValue(speed, newValue, DataIndex::speed); }
virtual void setHeading(double newValue) { updateValue(heading, newValue, DataIndex::heading); }
/********** Getters **********/
virtual string getCategory() { return category; };
virtual bool getAlive() { return alive; }
virtual unsigned char getCoalition() { return coalition; }
virtual string getName() { return name; }
virtual Coords getPosition() { return position; }
virtual double getSpeed() { return speed; }
virtual double getHeading() { return heading; }
protected:
unsigned int ID;
string category;
bool alive = false;
unsigned char coalition = NULL;
string name = "";
Coords position = Coords(NULL);
double speed = NULL;
double heading = NULL;
/********** Other **********/
map<unsigned char, unsigned long long> updateTimeMap;
/********** Private methods **********/
void appendString(stringstream& ss, const unsigned char& datumIndex, const string& datumValue) {
const unsigned short size = static_cast<unsigned short>(datumValue.size());
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&size, sizeof(unsigned short));
ss << datumValue;
}
/********** Template methods **********/
template <typename T>
void updateValue(T& value, T& newValue, unsigned char datumIndex)
{
if (newValue != value)
{
triggerUpdate(datumIndex);
value = newValue;
}
}
template <typename T>
void appendNumeric(stringstream& ss, const unsigned char& datumIndex, T& datumValue) {
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&datumValue, sizeof(T));
}
template <typename T>
void appendVector(stringstream& ss, const unsigned char& datumIndex, vector<T>& datumValue) {
const unsigned short size = datumValue.size();
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&size, sizeof(unsigned short));
for (auto& el : datumValue)
ss.write((const char*)&el, sizeof(T));
}
template <typename T>
void appendList(stringstream& ss, const unsigned char& datumIndex, list<T>& datumValue) {
const unsigned short size = datumValue.size();
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&size, sizeof(unsigned short));
for (auto& el : datumValue)
ss.write((const char*)&el, sizeof(T));
}
};
class Missile : public Weapon
{
public:
Missile(json::value json, unsigned int ID);
};
class Bomb : public Weapon
{
public:
Bomb(json::value json, unsigned int ID);
};
class Shell : public Weapon
{
public:
Shell(json::value json, unsigned int ID);
};

View File

@@ -0,0 +1,21 @@
#pragma once
#include "framework.h"
#include "dcstools.h"
class Weapon;
class WeaponsManager
{
public:
WeaponsManager(lua_State* L);
~WeaponsManager();
map<unsigned int, Weapon*>& getWeapons() { return weapons; };
Weapon* getWeapon(unsigned int ID);
void update(json::value& missionData, double dt);
void getWeaponData(stringstream& ss, unsigned long long time);
private:
map<unsigned int, Weapon*> weapons;
};

14
backend/core/resource.h Normal file
View File

@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by core.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,71 @@
#include "aircraft.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 Aircraft::database = json::value();
extern string instancePath;
void Aircraft::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("Aircrafts database loaded correctly from " + instancePath + path);
else
log("Error reading Aircrafts database file");
}
/* Aircraft */
Aircraft::Aircraft(json::value json, unsigned int ID) : AirUnit(json, ID)
{
log("New Aircraft created with ID: " + to_string(ID));
setCategory("Aircraft");
setDesiredSpeed(knotsToMs(300));
setDesiredAltitude(ftToM(20000));
};
void Aircraft::changeSpeed(string change)
{
if (change.compare("stop") == 0)
setState(State::IDLE);
else if (change.compare("slow") == 0)
setDesiredSpeed(getDesiredSpeed() - knotsToMs(25));
else if (change.compare("fast") == 0)
setDesiredSpeed(getDesiredSpeed() + knotsToMs(25));
if (getDesiredSpeed() < knotsToMs(50))
setDesiredSpeed(knotsToMs(50));
}
void Aircraft::changeAltitude(string change)
{
if (change.compare("descend") == 0)
{
if (getDesiredAltitude() > 5000)
setDesiredAltitude(getDesiredAltitude() - ftToM(2500));
else if (getDesiredAltitude() > 0)
setDesiredAltitude(getDesiredAltitude() - ftToM(500));
}
else if (change.compare("climb") == 0)
{
if (getDesiredAltitude() > 5000)
setDesiredAltitude(getDesiredAltitude() + ftToM(2500));
else if (getDesiredAltitude() >= 0)
setDesiredAltitude(getDesiredAltitude() + ftToM(500));
}
if (getDesiredAltitude() < 0)
setDesiredAltitude(0);
}

View File

@@ -0,0 +1,431 @@
#include "airunit.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;
/* Air unit */
AirUnit::AirUnit(json::value json, unsigned int ID) : Unit(json, ID)
{
};
void AirUnit::setDefaults(bool force)
{
if (!getAlive() || !getControlled() || getHuman() || !getIsLeader()) return;
/* Set the default IDLE state */
setState(State::IDLE);
/* Set desired altitude to be equal to current altitude so the unit does not climb/descend after spawn */
setDesiredAltitude(position.alt);
/* Set the default options */
setROE(ROE::OPEN_FIRE_WEAPON_FREE, force);
setReactionToThreat(ReactionToThreat::EVADE_FIRE, force);
setEmissionsCountermeasures(EmissionCountermeasure::DEFEND, force);
strcpy_s(TACAN.callsign, 4, "TKR");
setTACAN(TACAN, force);
setRadio(radio, force);
setGeneralSettings(generalSettings, force);
}
void AirUnit::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::FOLLOW: {
setLeaderID(NULL);
break;
}
case State::LAND: {
break;
}
case State::REFUEL: {
break;
}
case State::BOMB_POINT:
case State::CARPET_BOMB:
case State::BOMB_BUILDING: {
setTargetPosition(Coords(NULL));
break;
}
case State::LAND_AT_POINT: {
break;
}
default:
break;
}
}
/************ Perform any action required when ENTERING a state ************/
switch (newState) {
case State::IDLE: {
setEnableTaskCheckFailed(false);
clearActivePath();
resetActiveDestination();
break;
}
case State::REACH_DESTINATION: {
setEnableTaskCheckFailed(true);
resetActiveDestination();
break;
}
case State::ATTACK: {
setEnableTaskCheckFailed(true);
if (isTargetAlive()) {
Unit* target = unitsManager->getUnit(targetID);
Coords targetPosition = Coords(target->getPosition().lat, target->getPosition().lng, 0);
clearActivePath();
pushActivePathFront(targetPosition);
resetActiveDestination();
}
break;
}
case State::FOLLOW: {
setEnableTaskCheckFailed(true);
clearActivePath();
resetActiveDestination();
break;
}
case State::LAND: {
setEnableTaskCheckFailed(false);
resetActiveDestination();
break;
}
case State::REFUEL: {
setEnableTaskCheckFailed(true);
initialFuel = fuel;
clearActivePath();
resetActiveDestination();
break;
}
case State::BOMB_POINT:
case State::CARPET_BOMB:
case State::BOMB_BUILDING: {
setTargetPosition(currentTargetPosition);
setEnableTaskCheckFailed(true);
clearActivePath();
resetActiveDestination();
break;
}
case State::LAND_AT_POINT: {
setEnableTaskCheckFailed(true);
resetActiveDestination();
break;
}
default:
break;
}
setHasTask(false);
resetTaskFailedCounter();
log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState));
state = newState;
triggerUpdate(DataIndex::state);
AIloop();
}
void AirUnit::AIloop()
{
srand(static_cast<unsigned int>(time(NULL)) + ID);
/* Reset the anchor */
if (state != State::IDLE) {
setRacetrackAnchor(Coords(NULL));
setRacetrackBearing(NULL);
setRacetrackLength(NULL);
}
/* State machine */
switch (state) {
case State::IDLE: {
if (isActiveTanker)
setTask("Tanker racetrack");
else if (isActiveAWACS)
setTask("AWACS racetrack");
else
setTask("Idle");
if (!getHasTask())
{
if (racetrackAnchor == Coords(NULL)) setRacetrackAnchor(position);
if (racetrackBearing == NULL) setRacetrackBearing(heading);
std::ostringstream taskSS;
if (isActiveTanker) {
taskSS << "{ [1] = { id = 'Tanker' }, [2] = { id = 'Orbit', pattern = 'Race-Track', altitude = " <<
desiredAltitude << ", lat = " << racetrackAnchor.lat << ", lng = " << racetrackAnchor.lng << ", speed = " << desiredSpeed << ", altitudeType = '" <<
(desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "', heading = " <<
racetrackBearing << ", length = " << (racetrackLength != NULL ? racetrackLength : (50000 * 1.852)) << " }}";
}
else if (isActiveAWACS) {
taskSS << "{ [1] = { id = 'AWACS' }, [2] = { id = 'Orbit', pattern = 'Race-Track', altitude = " <<
desiredAltitude << ", lat = " << racetrackAnchor.lat << ", lng = " << racetrackAnchor.lng << ", speed = " << desiredSpeed << ", altitudeType = '" <<
(desiredAltitudeType ? "AGL" : "ASL") << "', speedType = '" << (desiredSpeedType ? "GS" : "CAS") << "', heading = " <<
racetrackBearing << ", length = " << (racetrackLength != NULL ? racetrackLength : (desiredSpeed * 30)) << " }}";
}
else {
taskSS << "{ id = 'Orbit', pattern = 'Race-Track', altitude = " <<
desiredAltitude << ", lat = " << racetrackAnchor.lat << ", lng = " << racetrackAnchor.lng << ", speed = " << desiredSpeed << ", altitudeType = '" <<
(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); }));
scheduler->appendCommand(command);
setHasTask(true);
}
break;
}
case State::REACH_DESTINATION: {
string enrouteTask = "";
bool looping = false;
if (isActiveTanker)
{
enrouteTask = "{ id = 'Tanker' }";
setTask("Tanker");
}
else if (isActiveAWACS)
{
enrouteTask = "{ id = 'AWACS' }";
setTask("AWACS");
}
else
{
enrouteTask = "nil";
setTask("Reaching destination");
}
if (activeDestination == NULL || !getHasTask())
{
if (!setActiveDestination())
setState(State::IDLE);
else
goToDestination(enrouteTask);
}
else {
if (isDestinationReached(getDestinationReachedThreshold())) {
if (updateActivePath(looping) && setActiveDestination())
goToDestination(enrouteTask);
else
setState(State::IDLE);
}
}
break;
}
case State::LAND: {
string enrouteTask = "{ id = 'Land' }";
setTask("Landing");
if (activeDestination == NULL)
{
setActiveDestination();
goToDestination(enrouteTask);
}
break;
}
case State::ATTACK: {
/* If the target is not alive (either not set or was succesfully destroyed) go back to REACH_DESTINATION */
if (!isTargetAlive()) {
setState(State::REACH_DESTINATION);
break;
}
/* Attack state is an "enroute" task, meaning the unit will keep trying to attack even if a new destination is set. This is useful to
manoeuvre the unit so that it can detect and engage the target. */
std::ostringstream enrouteTaskSS;
enrouteTaskSS << "{"
<< "id = 'EngageUnit'" << ","
<< "targetID = " << targetID << ","
<< "}";
string enrouteTask = enrouteTaskSS.str();
setTask("Attacking " + getTargetName());
if (!getHasTask())
{
setActiveDestination();
goToDestination(enrouteTask);
}
break;
}
case State::FOLLOW: {
clearActivePath();
activeDestination = Coords(NULL);
/* If the leader is not alive (either not set or was destroyed) go back to IDLE */
if (!isLeaderAlive()) {
setState(State::IDLE);
break;
}
setTask("Following " + getTargetName());
Unit* leader = unitsManager->getUnit(leaderID);
if (!getHasTask()) {
if (leader != nullptr && leader->getAlive() && formationOffset != NULL)
{
std::ostringstream taskSS;
taskSS << "{"
<< "id = 'FollowUnit'" << ", "
<< "leaderID = " << leader->getID() << ","
<< "offset = {"
<< "x = " << formationOffset.x << ","
<< "y = " << formationOffset.y << ","
<< "z = " << formationOffset.z
<< "},"
<< "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
}
break;
}
case State::REFUEL: {
setTask("Refueling");
if (!getHasTask()) {
if (fuel <= initialFuel) {
std::ostringstream taskSS;
taskSS << "{"
<< "id = 'Refuel'"
<< "}";
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::BOMB_POINT: {
setTask("Bombing point");
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'Bombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
break;
}
case State::CARPET_BOMB: {
setTask("Carpet bombing");
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'CarpetBombing', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
break;
}
case State::BOMB_BUILDING: {
setTask("Bombing building");
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'AttackMapObject', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
break;
}
case State::LAND_AT_POINT: {
setTask("Landing at point");
if (!getHasTask()) {
setActiveDestination();
std::ostringstream taskSS;
taskSS.precision(10),
taskSS << "{"
<< "id = 'LandAtPoint', "
<< "lat = " << activeDestination.lat << ", "
<< "lng = " << activeDestination.lng
<< "}";
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
break;
}
default:
break;
}
}
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);
}
}

View File

@@ -0,0 +1,318 @@
#include "commands.h"
#include "logger.h"
#include "dcstools.h"
#include "unit.h"
#include "unitsmanager.h"
extern UnitsManager* unitsManager;
/* Move command */
string Move::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.move, "
<< "\"" << groupName << "\"" << ", "
<< destination.lat << ", "
<< destination.lng << ", "
<< altitude << ", "
<< "\"" << altitudeType << "\"" << ", "
<< speed << ", "
<< "\"" << speedType << "\"" << ", "
<< "\"" << category << "\"" << ", "
<< taskOptions;
return commandSS.str();
}
/* Smoke command */
string Smoke::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.smoke, "
<< "\"" << color << "\"" << ", "
<< location.lat << ", "
<< location.lng;
return commandSS.str();
}
/* Spawn ground units command */
string SpawnGroundUnits::getString()
{
std::ostringstream unitsSS;
unitsSS.precision(10);
for (int i = 0; i < spawnOptions.size(); i++) {
unitsSS << "[" << i + 1 << "] = {"
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
<< "lat = " << spawnOptions[i].location.lat << ", "
<< "lng = " << spawnOptions[i].location.lng << ", "
<< "heading = " << spawnOptions[i].heading << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
}
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.spawnUnits, {"
<< "category = " << "\"" << "GroundUnit" << "\"" << ", "
<< "coalition = " << "\"" << coalition << "\"" << ", "
<< "country = \"" << country << "\", "
<< "units = " << "{" << unitsSS.str() << "}" << "}";
return commandSS.str();
}
/* Spawn ground units command */
string SpawnNavyUnits::getString()
{
std::ostringstream unitsSS;
unitsSS.precision(10);
for (int i = 0; i < spawnOptions.size(); i++) {
unitsSS << "[" << i + 1 << "] = {"
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
<< "lat = " << spawnOptions[i].location.lat << ", "
<< "lng = " << spawnOptions[i].location.lng << ", "
<< "heading = " << spawnOptions[i].heading << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
}
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.spawnUnits, {"
<< "category = " << "\"" << "NavyUnit" << "\"" << ", "
<< "coalition = " << "\"" << coalition << "\"" << ", "
<< "country = \"" << country << "\", "
<< "units = " << "{" << unitsSS.str() << "}" << "}";
return commandSS.str();
}
/* Spawn aircrafts command */
string SpawnAircrafts::getString()
{
std::ostringstream unitsSS;
unitsSS.precision(10);
for (int i = 0; i < spawnOptions.size(); i++) {
unitsSS << "[" << i + 1 << "] = {"
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
<< "lat = " << spawnOptions[i].location.lat << ", "
<< "lng = " << spawnOptions[i].location.lng << ", "
<< "alt = " << spawnOptions[i].location.alt << ", "
<< "heading = " << spawnOptions[i].heading << ", "
<< "loadout = \"" << spawnOptions[i].loadout << "\"" << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
}
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.spawnUnits, {"
<< "category = " << "\"" << "Aircraft" << "\"" << ", "
<< "coalition = " << "\"" << coalition << "\"" << ", "
<< "airbaseName = \"" << airbaseName << "\", "
<< "country = \"" << country << "\", "
<< "units = " << "{" << unitsSS.str() << "}" << "}";
return commandSS.str();
}
/* Spawn helicopters command */
string SpawnHelicopters::getString()
{
std::ostringstream unitsSS;
unitsSS.precision(10);
for (int i = 0; i < spawnOptions.size(); i++) {
unitsSS << "[" << i + 1 << "] = {"
<< "unitType = " << "\"" << spawnOptions[i].unitType << "\"" << ", "
<< "lat = " << spawnOptions[i].location.lat << ", "
<< "lng = " << spawnOptions[i].location.lng << ", "
<< "alt = " << spawnOptions[i].location.alt << ", "
<< "heading = " << spawnOptions[i].heading << ", "
<< "loadout = \"" << spawnOptions[i].loadout << "\"" << ", "
<< "liveryID = " << "\"" << spawnOptions[i].liveryID << "\"" << ", "
<< "skill = \"" << spawnOptions[i].skill << "\"" << "}, ";
}
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.spawnUnits, {"
<< "category = " << "\"" << "Helicopter" << "\"" << ", "
<< "coalition = " << "\"" << coalition << "\"" << ", "
<< "airbaseName = \"" << airbaseName << "\", "
<< "country = \"" << country << "\", "
<< "units = " << "{" << unitsSS.str() << "}" << "}";
return commandSS.str();
}
/* Clone unit command */
string Clone::getString()
{
std::ostringstream unitsSS;
unitsSS.precision(10);
for (int i = 0; i < cloneOptions.size(); i++) {
unitsSS << "[" << i + 1 << "] = {"
<< "ID = " << cloneOptions[i].ID << ", "
<< "lat = " << cloneOptions[i].location.lat << ", "
<< "lng = " << cloneOptions[i].location.lng << " }, ";
}
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.clone, "
<< "{" << unitsSS.str() << "}" << ", "
<< (deleteOriginal ? "true" : "false");
return commandSS.str();
}
/* Delete unit command */
string Delete::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.delete, "
<< ID << ", "
<< (explosion ? "true" : "false") << ", "
<< "\"" << explosionType << "\"";
return commandSS.str();
}
/* Set task command */
string SetTask::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.setTask, "
<< "\"" << groupName << "\"" << ", "
<< task;
return commandSS.str();
}
/* Reset task command */
string ResetTask::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.resetTask, "
<< "\"" << groupName << "\"";
return commandSS.str();
}
/* Set command command */
string SetCommand::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.setCommand, "
<< "\"" << groupName << "\"" << ", "
<< command;
return commandSS.str();
}
/* Set option command */
string SetOption::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
if (!isBoolean) {
commandSS << "Olympus.setOption, "
<< "\"" << groupName << "\"" << ", "
<< optionID << ", "
<< optionValue;
} else {
commandSS << "Olympus.setOption, "
<< "\"" << groupName << "\"" << ", "
<< optionID << ", "
<< (optionBool? "true": "false");
}
return commandSS.str();
}
/* Set onOff command */
string SetOnOff::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.setOnOff, "
<< "\"" << groupName << "\"" << ", "
<< (onOff ? "true" : "false");
return commandSS.str();
}
/* Explosion command */
string Explosion::getString()
{
std::ostringstream commandSS;
commandSS.precision(10);
commandSS << "Olympus.explosion, "
<< intensity << ", "
<< "\"" << explosionType << "\"" << ", "
<< location.lat << ", "
<< location.lng;
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();
}

178
backend/core/src/core.cpp Normal file
View File

@@ -0,0 +1,178 @@
#include "dcstools.h"
#include "logger.h"
#include "defines.h"
#include "unitsManager.h"
#include "weaponsManager.h"
#include "server.h"
#include "scheduler.h"
#include "scriptLoader.h"
#include "luatools.h"
#include <chrono>
using namespace std::chrono;
auto lastUnitsUpdate = std::chrono::system_clock::now();
auto lastWeaponsUpdate = std::chrono::system_clock::now();
auto lastExecution = std::chrono::system_clock::now();
/* Singleton objects */
UnitsManager* unitsManager = nullptr;
WeaponsManager* weaponsManager = nullptr;
Server* server = nullptr;
Scheduler* scheduler = nullptr;
/* Data jsons */
json::value missionData = json::value::object();
json::value drawingsByLayer = json::value::object();
mutex mutexLock;
string sessionHash;
string instancePath;
bool initialized = false;
unsigned int frameCounter = 0;
/* Called when DCS simulation stops. All singleton instances are deleted. */
extern "C" DllExport int coreDeinit(lua_State* L)
{
if (!initialized)
return (0);
log("Olympus coreDeinit called successfully");
server->stop(L);
delete unitsManager;
delete weaponsManager;
delete server;
delete scheduler;
log("All singletons objects destroyed successfully");
return(0);
}
/* Called when DCS simulation starts. All singletons are instantiated, and the custom Lua functions are registered in the Lua state. */
extern "C" DllExport int coreInit(lua_State* L, const char* path)
{
instancePath = path;
log("Initializing core.dll with instance path " + instancePath);
sessionHash = random_string(16);
log("Random session hash " + sessionHash);
unitsManager = new UnitsManager(L);
weaponsManager = new WeaponsManager(L);
server = new Server(L);
scheduler = new Scheduler(L);
registerLuaFunctions(L);
server->start(L);
unitsManager->loadDatabases();
initialized = true;
return(0);
}
extern "C" DllExport int coreFrame(lua_State* L)
{
if (!initialized)
return (0);
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
frameCounter++;
const std::chrono::duration<double> executionDuration = std::chrono::system_clock::now() - lastExecution;
if (executionDuration.count() > (20 * FRAMERATE_TIME_INTERVAL)) {
if (executionDuration.count() > 0) {
scheduler->setFrameRate(frameCounter / executionDuration.count());
frameCounter = 0;
}
lastExecution = std::chrono::system_clock::now();
}
if (scheduler != nullptr)
scheduler->execute(L);
return(0);
}
extern "C" DllExport int coreUnitsData(lua_State * L)
{
if (!initialized)
return (0);
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
json::value unitsData = json::value::object();
lua_getglobal(L, "Olympus");
lua_getfield(L, -1, "unitsData");
luaTableToJSON(L, -1, unitsData);
const std::chrono::duration<double> updateDuration = std::chrono::system_clock::now() - lastUnitsUpdate;
if (unitsData.has_object_field(L"units")) {
unitsManager->update(unitsData[L"units"], updateDuration.count());
}
lastUnitsUpdate = std::chrono::system_clock::now();
return(0);
}
extern "C" DllExport int coreWeaponsData(lua_State * L)
{
if (!initialized)
return (0);
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
json::value weaponsData = json::value::object();
lua_getglobal(L, "Olympus");
lua_getfield(L, -1, "weaponsData");
luaTableToJSON(L, -1, weaponsData);
const std::chrono::duration<double> updateDuration = std::chrono::system_clock::now() - lastWeaponsUpdate;
if (weaponsData.has_object_field(L"weapons")) {
weaponsManager->update(weaponsData[L"weapons"], updateDuration.count());
}
lastWeaponsUpdate = std::chrono::system_clock::now();
return(0);
}
extern "C" DllExport int coreMissionData(lua_State * L)
{
if (!initialized)
return (0);
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
lua_getglobal(L, "Olympus");
lua_getfield(L, -1, "missionData");
luaTableToJSON(L, -1, missionData);
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);
}

View File

@@ -0,0 +1,30 @@
#include "datatypes.h"
bool operator==(const DataTypes::TACAN& lhs, const DataTypes::TACAN& rhs)
{
return lhs.isOn == rhs.isOn && lhs.channel == rhs.channel && lhs.XY == rhs.XY && strcmp(lhs.callsign, rhs.callsign) == 0;
}
bool operator==(const DataTypes::Radio& lhs, const DataTypes::Radio& rhs)
{
return lhs.frequency == rhs.frequency && lhs.callsign == rhs.callsign && lhs.callsignNumber == rhs.callsignNumber;
}
bool operator==(const DataTypes::GeneralSettings& lhs, const DataTypes::GeneralSettings& rhs)
{
return lhs.prohibitAA == rhs.prohibitAA && lhs.prohibitAfterburner == rhs.prohibitAfterburner && lhs.prohibitAG == rhs.prohibitAG &&
lhs.prohibitAirWpn == rhs.prohibitAirWpn && lhs.prohibitJettison == rhs.prohibitJettison;
}
bool operator==(const DataTypes::Ammo& lhs, const DataTypes::Ammo& rhs)
{
return lhs.category == rhs.category && lhs.guidance == rhs.guidance && lhs.missileCategory == rhs.missileCategory &&
lhs.quantity == rhs.quantity && strcmp(lhs.name, rhs.name) == 0;
}
bool operator==(const DataTypes::Contact& lhs, const DataTypes::Contact& rhs)
{
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

@@ -0,0 +1,71 @@
#include "helicopter.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 Helicopter::database = json::value();
extern string instancePath;
void Helicopter::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("Helicopters database loaded correctly from " + instancePath + path);
else
log("Error reading Helicopters database file");
}
/* Helicopter */
Helicopter::Helicopter(json::value json, unsigned int ID) : AirUnit(json, ID)
{
log("New Helicopter created with ID: " + to_string(ID));
setCategory("Helicopter");
setDesiredSpeed(knotsToMs(100));
setDesiredAltitude(ftToM(5000));
};
void Helicopter::changeSpeed(string change)
{
if (change.compare("stop") == 0)
setState(State::IDLE);
else if (change.compare("slow") == 0)
setDesiredSpeed(getDesiredSpeed() - knotsToMs(10));
else if (change.compare("fast") == 0)
setDesiredSpeed(getDesiredSpeed() + knotsToMs(10));
if (getDesiredSpeed() < knotsToMs(0))
setDesiredSpeed(knotsToMs(0));
}
void Helicopter::changeAltitude(string change)
{
if (change.compare("descend") == 0)
{
if (getDesiredAltitude() > 100)
setDesiredAltitude(getDesiredAltitude() - ftToM(100));
else if (getDesiredAltitude() > 0)
setDesiredAltitude(getDesiredAltitude() - ftToM(10));
}
else if (change.compare("climb") == 0)
{
if (getDesiredAltitude() > 100)
setDesiredAltitude(getDesiredAltitude() + ftToM(100));
else if (getDesiredAltitude() >= 0)
setDesiredAltitude(getDesiredAltitude() + ftToM(10));
}
if (getDesiredAltitude() < 0)
setDesiredAltitude(0);
}

View File

@@ -0,0 +1,267 @@
#include "navyunit.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 NavyUnit::database = json::value();
extern string instancePath;
void NavyUnit::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("NavyUnits database loaded correctly from " + instancePath + path);
else
log("Error reading NavyUnits database file");
}
/* Navy Unit */
NavyUnit::NavyUnit(json::value json, unsigned int ID) : Unit(json, ID)
{
log("New Navy Unit created with ID: " + to_string(ID));
setCategory("NavyUnit");
setDesiredSpeed(10);
};
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;
/* 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 NavyUnit::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: {
setEnableTaskCheckFailed(false);
clearActivePath();
resetActiveDestination();
break;
}
case State::REACH_DESTINATION: {
setEnableTaskCheckFailed(true);
resetActiveDestination();
break;
}
case State::ATTACK: {
setEnableTaskCheckFailed(true);
clearActivePath();
resetActiveDestination();
break;
}
case State::FIRE_AT_AREA: {
setTargetPosition(currentTargetPosition);
setEnableTaskCheckFailed(true);
clearActivePath();
resetActiveDestination();
break;
}
case State::SIMULATE_FIRE_FIGHT: {
setTargetPosition(currentTargetPosition);
setEnableTaskCheckFailed(false);
clearActivePath();
resetActiveDestination();
break;
}
case State::SCENIC_AAA: {
setEnableTaskCheckFailed(false);
clearActivePath();
resetActiveDestination();
break;
}
case State::MISS_ON_PURPOSE: {
setEnableTaskCheckFailed(false);
clearActivePath();
resetActiveDestination();
break;
}
default:
break;
}
setHasTask(false);
resetTaskFailedCounter();
log(unitName + " setting state from " + to_string(state) + " to " + to_string(newState));
state = newState;
triggerUpdate(DataIndex::state);
AIloop();
}
void NavyUnit::AIloop()
{
srand(static_cast<unsigned int>(time(NULL)) + ID);
switch (state) {
case State::IDLE: {
setTask("Idle");
if (getHasTask())
resetTask();
break;
}
case State::REACH_DESTINATION: {
string enrouteTask = "{}";
bool looping = false;
if (activeDestination == NULL || !getHasTask())
{
if (!setActiveDestination())
setState(State::IDLE);
else
goToDestination(enrouteTask);
}
else {
if (isDestinationReached(NAVY_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: {
setTask("Firing at area");
if (!getHasTask()) {
std::ostringstream taskSS;
taskSS.precision(10);
taskSS << "{id = 'FireAtPoint', lat = " << targetPosition.lat << ", lng = " << targetPosition.lng << ", radius = 1000}";
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: {
setTask("Simulating fire fight");
// TODO
setState(State::IDLE);
break;
}
default:
break;
}
}
void NavyUnit::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 NavyUnit::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);
}
}

View File

@@ -0,0 +1,833 @@
#include "scheduler.h"
#include "logger.h"
#include "dcstools.h"
#include "unitsManager.h"
#include "utils.h"
#include "unit.h"
extern UnitsManager* unitsManager;
Scheduler::Scheduler(lua_State* L)
{
LogInfo(L, "Scheduler constructor called successfully");
}
Scheduler::~Scheduler()
{
}
/* Appends a */
void Scheduler::appendCommand(Command* newCommand)
{
for (auto command : commands) {
if (command->getString().compare(newCommand->getString()) == 0 && command->getPriority() == newCommand->getPriority())
return;
}
commands.push_back(newCommand);
}
int Scheduler::getLoad()
{
int currentLoad = 0;
for (auto command : commands) {
currentLoad += command->getLoad();
}
return currentLoad;
}
void Scheduler::execute(lua_State* L)
{
/* Decrease the active computation load. New commands can be sent only if the load has reached 0.
This is needed to avoid server lag. */
if (load > 0) {
load--;
return;
}
int priority = CommandPriority::IMMEDIATE;
while (priority >= CommandPriority::LOW) {
for (auto command : commands)
{
if (command->getPriority() == priority)
{
string commandString = "Olympus.protectedCall(" + command->getString() + ")";
if (dostring_in(L, "server", (commandString)))
log("Error executing command " + commandString);
else
log("Command '" + commandString + "' executed correctly, current load " + to_string(getLoad()));
/* Adjust the load depending on the fps */
double fpsMultiplier = 20;
if (getFrameRate() + 3 > 0)
fpsMultiplier = static_cast<unsigned int>(max(1, 60 / (getFrameRate() + 3))); /* Multiplier between 1 and 20 */
load = static_cast<unsigned int>(command->getLoad() * fpsMultiplier);
commands.remove(command);
executedCommandsHashes.push_back(command->getHash());
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;
return;
}
}
priority--;
};
}
void Scheduler::setCommandModeOptions(json::value value) {
if (value.has_boolean_field(L"restrictSpawns"))
setRestrictSpawns(value[L"restrictSpawns"].as_bool());
if (value.has_boolean_field(L"restrictToCoalition"))
setRestrictToCoalition(value[L"restrictToCoalition"].as_bool());
if (value.has_number_field(L"setupTime"))
setSetupTime(value[L"setupTime"].as_number().to_int32());
if (value.has_object_field(L"spawnPoints")) {
if (value[L"spawnPoints"].has_number_field(L"blue"))
setBlueSpawnPoints(value[L"spawnPoints"][L"blue"].as_number().to_int32());
if (value[L"spawnPoints"].has_number_field(L"red"))
setRedSpawnPoints(value[L"spawnPoints"][L"red"].as_number().to_int32());
}
if (value.has_array_field(L"eras")) {
int length = static_cast<int>(value[L"eras"].as_array().size());
vector<string> newEras;
for (int idx = 0; idx < length; idx++)
newEras.push_back(to_string(value[L"eras"].as_array().at(idx)));
setEras(newEras);
}
}
json::value Scheduler::getCommandModeOptions() {
json::value json = json::value::object();
json[L"restrictSpawns"] = json::value(getRestrictSpawns());
json[L"restrictToCoalition"] = json::value(getRestrictToCoalition());
json[L"setupTime"] = json::value(getSetupTime());
json[L"spawnPoints"] = json::value::object();
json[L"spawnPoints"][L"blue"] = json::value(getBlueSpawnPoints());
json[L"spawnPoints"][L"red"] = json::value(getRedSpawnPoints());
int idx = 0;
json[L"eras"] = json::value::array();
for (string era : getEras())
json[L"eras"][idx++] = json::value(to_wstring(era));
return json;
}
bool Scheduler::checkSpawnPoints(int spawnPoints, string coalition)
{
if (!getRestrictSpawns()) return true;
if (coalition.compare("blue") == 0) {
if (getBlueSpawnPoints() - spawnPoints >= 0) {
setBlueSpawnPoints(getBlueSpawnPoints() - spawnPoints);
return true;
}
else {
log("Not enough blue coalition spawn points available. Available: " + to_string(getBlueSpawnPoints()) + ", required: " + to_string(spawnPoints));
return false;
}
}
else if (coalition.compare("red") == 0) {
if (getRedSpawnPoints() - spawnPoints >= 0) {
setRedSpawnPoints(getRedSpawnPoints() - spawnPoints);
return true;
}
else {
log("Not enough red coalition spawn points available. Available: " + to_string(getRedSpawnPoints()) + ", required: " + to_string(spawnPoints));
return false;
}
}
return false;
}
void Scheduler::handleRequest(string key, json::value value, string username, json::value& answer)
{
Command* command = nullptr;
log("Received request with ID: " + key);
log(L"Incoming command raw value: " + value.serialize());
/************************/
if (key.compare("setPath") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
{
json::value path = value[L"path"];
list<Coords> newPath;
for (unsigned int i = 0; i < path.as_array().size(); i++)
{
string WP = to_string(i);
double lat = path[i][L"lat"].as_double();
double lng = path[i][L"lng"].as_double();
Coords dest; dest.lat = lat; dest.lng = lng;
newPath.push_back(dest);
}
unit->setActivePath(newPath);
unit->setState(State::REACH_DESTINATION);
log(username + " updated destination path for unit " + unit->getUnitName() + "(" + unit->getName() + ")", true);
}
}
/************************/
else if (key.compare("smoke") == 0)
{
string color = to_string(value[L"color"]);
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;
command = dynamic_cast<Command*>(new Smoke(color, loc));
log(username + " added a " + color + " smoke at (" + to_string(lat) + ", " + to_string(lng) + ")", true);
}
/************************/
else if (key.compare("spawnAircrafts") == 0 || key.compare("spawnHelicopters") == 0)
{
bool immediate = value[L"immediate"].as_bool();
string coalition = to_string(value[L"coalition"]);
string airbaseName = to_string(value[L"airbaseName"]);
string country = to_string(value[L"country"]);
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
if (!checkSpawnPoints(spawnPoints, coalition)) {
log(username + " insufficient spawn points ", true);
return;
}
vector<SpawnOptions> spawnOptions;
for (auto unit : value[L"units"].as_array()) {
string unitType = to_string(unit[L"unitType"]);
double lat = unit[L"location"][L"lat"].as_double();
double lng = unit[L"location"][L"lng"].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;
string loadout = to_string(unit[L"loadout"]);
string liveryID = to_string(unit[L"liveryID"]);
string skill = to_string(unit[L"skill"]);
spawnOptions.push_back({unitType, location, loadout, skill, liveryID, heading});
log(username + " spawned a " + coalition + " " + unitType , true);
}
if (key.compare("spawnAircrafts") == 0)
command = dynamic_cast<Command*>(new SpawnAircrafts(coalition, spawnOptions, airbaseName, country, immediate));
else
command = dynamic_cast<Command*>(new SpawnHelicopters(coalition, spawnOptions, airbaseName, country, immediate));
}
/************************/
else if (key.compare("spawnGroundUnits") == 0 || key.compare("spawnNavyUnits") == 0)
{
bool immediate = value[L"immediate"].as_bool();
string coalition = to_string(value[L"coalition"]);
string country = to_string(value[L"country"]);
int spawnPoints = value[L"spawnPoints"].as_number().to_int32();
if (!checkSpawnPoints(spawnPoints, coalition)) {
log(username + " insufficient spawn points ", true);
return;
}
vector<SpawnOptions> spawnOptions;
for (auto unit : value[L"units"].as_array()) {
string unitType = to_string(unit[L"unitType"]);
double lat = unit[L"location"][L"lat"].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;
string liveryID = to_string(unit[L"liveryID"]);
string skill = to_string(unit[L"skill"]);
spawnOptions.push_back({ unitType, location, "", skill, liveryID, heading});
log(username + " spawned a " + coalition + " " + unitType, true);
}
if (key.compare("spawnGroundUnits") == 0)
command = dynamic_cast<Command*>(new SpawnGroundUnits(coalition, spawnOptions, country, immediate));
else
command = dynamic_cast<Command*>(new SpawnNavyUnits(coalition, spawnOptions, country, immediate));
}
/************************/
else if (key.compare("attackUnit") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
unsigned int targetID = value[L"targetID"].as_integer();
Unit* unit = unitsManager->getGroupLeader(ID);
Unit* target = unitsManager->getUnit(targetID);
if (unit != nullptr && target != nullptr) {
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to attack unit " + target->getUnitName() + "(" + target->getName() + ")", true);
unit->setTargetID(targetID);
unit->setState(State::ATTACK);
}
}
/************************/
else if (key.compare("followUnit") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
unsigned int leaderID = value[L"targetID"].as_integer();
double offsetX = value[L"offsetX"].as_double();
double offsetY = value[L"offsetY"].as_double();
double offsetZ = value[L"offsetZ"].as_double();
Unit* unit = unitsManager->getGroupLeader(ID);
Unit* leader = unitsManager->getUnit(leaderID);
if (unit != nullptr && leader != nullptr) {
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to follow unit " + leader->getUnitName() + "(" + leader->getName() + ")", true);
unit->setFormationOffset(Offset(offsetX, offsetY, offsetZ));
unit->setLeaderID(leaderID);
unit->setState(State::FOLLOW);
}
}
/************************/
else if (key.compare("changeSpeed") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->changeSpeed(to_string(value[L"change"]));
log(username + " changed " + unit->getUnitName() + "(" + unit->getName() + ") speed: " + to_string(value[L"change"]), true);
}
}
/************************/
else if (key.compare("changeAltitude") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->changeAltitude(to_string(value[L"change"]));
log(username + " changed " + unit->getUnitName() + "(" + unit->getName() + ") altitude: " + to_string(value[L"change"]), true);
}
}
/************************/
else if (key.compare("setSpeed") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setDesiredSpeed(value[L"speed"].as_double());
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") speed: " + to_string(value[L"speed"].as_double()), true);
}
}
/************************/
else if (key.compare("setSpeedType") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setDesiredSpeedType(to_string(value[L"speedType"]));
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") speed type: " + to_string(value[L"speedType"]), true);
}
}
/************************/
else if (key.compare("setAltitude") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setDesiredAltitude(value[L"altitude"].as_double());
log(username + " set " + unit->getUnitName() + "(" + unit->getName() + ") altitude: " + to_string(value[L"altitude"].as_double()), true);
}
}
/************************/
else if (key.compare("setAltitudeType") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setDesiredAltitudeType(to_string(value[L"altitudeType"]));
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)
{
vector<CloneOptions> cloneOptions;
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()) {
unsigned int ID = unit[L"ID"].as_integer();
double lat = unit[L"location"][L"lat"].as_double();
double lng = unit[L"location"][L"lng"].as_double();
Coords location; location.lat = lat; location.lng = lng;
cloneOptions.push_back({ ID, location });
log(username + " cloning unit with ID " + to_string(ID), true);
}
command = dynamic_cast<Command*>(new Clone(cloneOptions, deleteOriginal));
}
/************************/
else if (key.compare("setROE") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unsigned char ROE = value[L"ROE"].as_number().to_uint32();
unit->setROE(ROE);
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)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unsigned char reactionToThreat = value[L"reactionToThreat"].as_number().to_uint32();
unit->setReactionToThreat(reactionToThreat);
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") reaction to threat to " + to_string(reactionToThreat), true);
}
}
/************************/
else if (key.compare("setEmissionsCountermeasures") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unsigned char emissionsCountermeasures = value[L"emissionsCountermeasures"].as_number().to_uint32();
unit->setEmissionsCountermeasures(emissionsCountermeasures);
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") emissions and countermeasures to " + to_string(emissionsCountermeasures), true);
}
}
/************************/
else if (key.compare("landAt") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(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;
unit->landAt(loc);
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to land", true);
}
}
/************************/
else if (key.compare("deleteUnit") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
bool explosion = value[L"explosion"].as_bool();
string explosionType = to_string(value[L"explosionType"]);
bool immediate = value[L"immediate"].as_bool();
Unit* unit = unitsManager->getUnit(ID);
if (unit != nullptr) {
unitsManager->deleteUnit(ID, explosion, explosionType, immediate);
log(username + " deleted unit " + unit->getUnitName() + "(" + unit->getName() + ")", true);
}
}
/************************/
else if (key.compare("refuel") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setState(State::REFUEL);
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to refuel", true);
}
}
/************************/
else if (key.compare("setAdvancedOptions") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
{
/* Advanced tasking */
unit->setIsActiveTanker(value[L"isActiveTanker"].as_bool());
unit->setIsActiveAWACS(value[L"isActiveAWACS"].as_bool());
/* TACAN Options */
DataTypes::TACAN TACAN;
TACAN.isOn = value[L"TACAN"][L"isOn"].as_bool();
TACAN.channel = static_cast<unsigned char>(value[L"TACAN"][L"channel"].as_number().to_uint32());
TACAN.XY = to_string(value[L"TACAN"][L"XY"]).at(0);
string callsign = to_string(value[L"TACAN"][L"callsign"]);
if (callsign.length() > 3)
callsign = callsign.substr(0, 3);
strcpy_s(TACAN.callsign, 4, callsign.c_str());
unit->setTACAN(TACAN);
/* Radio Options */
auto radio = value[L"radio"];
unit->setRadio({ radio[L"frequency"].as_number().to_uint32(),
static_cast<unsigned char>(radio[L"callsign"].as_number().to_uint32()),
static_cast<unsigned char>(radio[L"callsignNumber"].as_number().to_uint32())
});
/* General Settings */
auto generalSettings = value[L"generalSettings"];
unit->setGeneralSettings({ generalSettings[L"prohibitJettison"].as_bool(),
generalSettings[L"prohibitAA"].as_bool(),
generalSettings[L"prohibitAG"].as_bool(),
generalSettings[L"prohibitAfterburner"].as_bool(),
generalSettings[L"prohibitAirWpn"].as_bool(),
});
unit->resetActiveDestination();
log(username + " updated unit " + unit->getUnitName() + "(" + unit->getName() + ") advancedOptions", true);
}
}
/************************/
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)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
bool followRoads = value[L"followRoads"].as_bool();
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setFollowRoads(followRoads);
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") followRoads to: " + (followRoads ? "true" : "false"), true);
}
}
/************************/
else if (key.compare("setOnOff") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
bool onOff = value[L"onOff"].as_bool();
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setOnOff(onOff);
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") onOff to: " + (onOff? "true": "false"), true);
}
}
/************************/
else if (key.compare("explosion") == 0)
{
unsigned int intensity = value[L"intensity"].as_integer();
string explosionType = to_string(value[L"explosionType"]);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
log("Adding explosion of type " + explosionType + " at (" + to_string(lat) + ", " + to_string(lng) + ")");
Coords loc; loc.lat = lat; loc.lng = lng;
command = dynamic_cast<Command*>(new Explosion(intensity, explosionType, loc));
}
/************************/
else if (key.compare("bombPoint") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setTargetPosition(loc);
unit->setState(State::BOMB_POINT);
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to bomb a point", true);
}
}
/************************/
else if (key.compare("carpetBomb") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setTargetPosition(loc);
unit->setState(State::CARPET_BOMB);
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to perform carpet bombing", true);
}
}
/************************/
/* TODO: this command does not appear to be working in DCS and has been disabled */
else if (key.compare("bombBuilding") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setTargetPosition(loc);
unit->setState(State::BOMB_BUILDING);
}
}
/************************/
else if (key.compare("fireAtArea") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
if (value[L"location"].has_number_field(L"alt")) {
loc.alt = value[L"location"][L"alt"].as_double();
}
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setTargetPosition(loc);
unit->setState(State::FIRE_AT_AREA);
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to fire at area", true);
}
}
/************************/
else if (key.compare("simulateFireFight") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
double alt = value[L"altitude"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng; loc.alt = alt;
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setTargetPosition(loc);
unit->setState(State::SIMULATE_FIRE_FIGHT);
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to simulate a fire fight", true);
}
}
/************************/
else if (key.compare("scenicAAA") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setState(State::SCENIC_AAA);
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to enter scenic AAA state", true);
}
}
/************************/
else if (key.compare("missOnPurpose") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unit->setState(State::MISS_ON_PURPOSE);
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to enter Miss On Purpose state", true);
}
}
/************************/
else if (key.compare("setOperateAs") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
unsigned char operateAs = value[L"operateAs"].as_number().to_uint32();
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->setOperateAs(operateAs);
}
/************************/
else if (key.compare("landAtPoint") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
Coords loc; loc.lat = lat; loc.lng = lng;
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
list<Coords> newPath;
newPath.push_back(loc);
unit->setActivePath(newPath);
unit->setState(State::LAND_AT_POINT);
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to land at point", true);
}
}
/************************/
else if (key.compare("setShotsScatter") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unsigned char shotsScatter = value[L"shotsScatter"].as_number().to_uint32();
unit->setShotsScatter(shotsScatter);
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") shots scatter to " + to_string(shotsScatter), true);
}
}
/************************/
else if (key.compare("setShotsIntensity") == 0)
{
unsigned int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr) {
unsigned char shotsIntensity = value[L"shotsIntensity"].as_number().to_uint32();
unit->setShotsIntensity(shotsIntensity);
log(username + " set unit " + unit->getUnitName() + "(" + unit->getName() + ") shots intensity to " + to_string(shotsIntensity), true);
}
}
/************************/
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);
log(username + " updated the Command Mode Options", true);
}
/************************/
else if (key.compare("reloadDatabases") == 0) {
unitsManager->loadDatabases();
}
/************************/
else
{
log("Unknown command: " + key);
}
if (command != nullptr)
{
appendCommand(command);
log("New command appended correctly to stack. Current server load: " + to_string(getLoad()));
answer[L"commandHash"] = json::value(to_wstring(command->getHash()));
}
}

View File

@@ -2,9 +2,12 @@
#include "logger.h"
#include "luatools.h"
#include "dcstools.h"
#include "defines.h"
#include <algorithm>
extern string instancePath;
bool executeLuaScript(lua_State* L, string path)
{
replace(path.begin(), path.end(), '\\', '/');
@@ -13,10 +16,12 @@ bool executeLuaScript(lua_State* L, string path)
if (dostring_in(L, "server", str.c_str()) != 0)
{
log("Error registering " + path);
return false;
}
else
{
log(path + " registered successfully");
return true;
}
}
@@ -34,20 +39,9 @@ void registerLuaFunctions(lua_State* L)
log("protectedCall registered successfully");
}
char* buf = nullptr;
size_t sz = 0;
if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr)
{
modLocation = buf;
free(buf);
}
else
{
log("DCSOLYMPUS_PATH environment variable is missing");
return;
}
executeLuaScript(L, modLocation + "\\Scripts\\mist_4_4_90.lua");
executeLuaScript(L, modLocation + "\\Scripts\\OlympusCommand.lua");
executeLuaScript(L, modLocation + "\\Scripts\\unitPayloads.lua");
executeLuaScript(L, instancePath + MIST_SCRIPT);
executeLuaScript(L, instancePath + OLYMPUS_COMMAND_SCRIPT);
executeLuaScript(L, instancePath + UNIT_PAYLOADS_SCRIPT);
executeLuaScript(L, instancePath + TEMPLATES_SCRIPT);
executeLuaScript(L, instancePath + MODS_SCRIPT);
}

353
backend/core/src/server.cpp Normal file
View File

@@ -0,0 +1,353 @@
#include "server.h"
#include "logger.h"
#include "defines.h"
#include "unitsManager.h"
#include "weaponsManager.h"
#include "scheduler.h"
#include "luatools.h"
#include <exception>
#include <stdexcept>
#include "base64.hpp"
#include <chrono>
using namespace std::chrono;
using namespace base64;
extern UnitsManager* unitsManager;
extern WeaponsManager* weaponsManager;
extern Scheduler* scheduler;
extern json::value missionData;
extern json::value drawingsByLayer;
extern mutex mutexLock;
extern string sessionHash;
extern string instancePath;
void handle_eptr(std::exception_ptr eptr)
{
try {
if (eptr) {
std::rethrow_exception(eptr);
}
}
catch (const std::exception& e) {
log(e.what());
}
}
Server::Server(lua_State* L):
serverThread(nullptr),
runListener(true)
{
}
void Server::start(lua_State* L)
{
log("Starting RESTServer");
serverThread = new thread(&Server::task, this);
}
void Server::stop(lua_State* L)
{
log("Stopping RESTServer");
runListener = false;
if (serverThread != nullptr)
serverThread->join();
}
void Server::handle_options(http_request request)
{
http_response response(status_codes::OK);
response.headers().add(U("Allow"), U("GET, PUT, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, PUT, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type, Authorization"));
request.reply(response);
}
void Server::handle_get(http_request request)
{
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
http_response response(status_codes::OK);
string password = extractPassword(request);
if (password.compare(gameMasterPassword) == 0 || password.compare(blueCommanderPassword) == 0 || password.compare(redCommanderPassword) == 0)
{
std::exception_ptr eptr;
try {
auto answer = json::value::object();
auto path = uri::split_path(uri::decode(request.relative_uri().path()));
/* If present, extract the request reference time. This is used for updates, and it specifies the last time that request has been performed */
map<utility::string_t, utility::string_t> query = request.relative_uri().split_query(request.relative_uri().query());
unsigned long long time = 0;
if (query.find(L"time") != query.end())
{
try {
time = stoull((*(query.find(L"time"))).second);
}
catch (...) {
time = 0;
}
}
if (path.size() > 0)
{
string URI = to_string(path[0]);
/* Units data */
if (URI.compare(UNITS_URI) == 0)
{
unsigned long long updateTime = ms.count();
stringstream ss;
ss.write((char*)&updateTime, sizeof(updateTime));
unitsManager->getUnitData(ss, time);
response.set_body(concurrency::streams::bytestream::open_istream(ss.str()));
}
else if (URI.compare(WEAPONS_URI) == 0)
{
unsigned long long updateTime = ms.count();
stringstream ss;
ss.write((char*)&updateTime, sizeof(updateTime));
weaponsManager->getWeaponData(ss, time);
response.set_body(concurrency::streams::bytestream::open_istream(ss.str()));
}
else {
/* Logs data */
if (URI.compare(LOGS_URI) == 0)
{
auto logs = json::value::object();
getLogsJSON(logs, time);
answer[L"logs"] = logs;
}
/* Airbases data */
else if (URI.compare(AIRBASES_URI) == 0 && missionData.has_object_field(L"airbases"))
answer[L"airbases"] = missionData[L"airbases"];
/* Bullseyes data */
else if (URI.compare(BULLSEYE_URI) == 0 && missionData.has_object_field(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 */
else if (URI.compare(MISSION_URI) == 0 && missionData.has_object_field(L"mission")) {
answer[L"mission"] = missionData[L"mission"];
answer[L"mission"][L"commandModeOptions"] = scheduler->getCommandModeOptions();
/* The active mode is determined by the inserted password*/
if (password.compare(gameMasterPassword) == 0)
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Game master");
else if (password.compare(blueCommanderPassword) == 0)
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Blue commander");
else if (password.compare(redCommanderPassword) == 0)
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Red commander");
else
answer[L"mission"][L"commandModeOptions"][L"commandMode"] = json::value(L"Observer");
}
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"])));
}
/* Drawings data*/
else if (URI.compare(DRAWINGS_URI) == 0 && drawingsByLayer.has_object_field(L"drawings")) {
answer[L"drawings"] = drawingsByLayer[L"drawings"];
}
/* Common data */
answer[L"time"] = json::value::string(to_wstring(ms.count()));
answer[L"sessionHash"] = json::value::string(to_wstring(sessionHash));
answer[L"load"] = scheduler->getLoad();
answer[L"frameRate"] = scheduler->getFrameRate();
response.set_body(answer);
}
}
}
catch (...) {
eptr = std::current_exception(); // capture
}
handle_eptr(eptr);
}
else {
response = status_codes::Unauthorized;
}
response.headers().add(U("Allow"), U("GET, PUT, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, PUT, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type, Authorization"));
request.reply(response);
}
void Server::handle_request(http_request request, function<void(json::value const&, json::value&)> action)
{
http_response response(status_codes::OK);
//TODO: limit what a user can do depending on the password
string password = extractPassword(request);
if (password.compare(gameMasterPassword) == 0 || password.compare(blueCommanderPassword) == 0 || password.compare(redCommanderPassword) == 0)
{
auto answer = json::value::object();
request.extract_json().then([&answer, &action](pplx::task<json::value> task)
{
try
{
auto const& jvalue = task.get();
if (!jvalue.is_null())
action(jvalue, answer);
}
catch (http_exception const& e)
{
log(e.what());
}
}).wait();
response.set_body(answer);
}
else {
response = status_codes::Unauthorized;
}
response.headers().add(U("Allow"), U("GET, PUT, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Origin"), U("*"));
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, PUT, OPTIONS"));
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type, Authorization"));
request.reply(response);
}
void Server::handle_put(http_request request)
{
string username = extractUsername(request);
handle_request(
request,
[username](json::value const& jvalue, json::value& answer)
{
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
for (auto const& e : jvalue.as_object())
{
auto key = e.first;
auto value = e.second;
std::exception_ptr eptr;
try {
scheduler->handleRequest(to_string(key), value, username, answer);
}
catch (...) {
eptr = std::current_exception(); // capture
}
handle_eptr(eptr);
}
});
}
string Server::extractUsername(http_request& request) {
if (request.headers().has(L"Authorization")) {
string authorization = to_string(request.headers().find(L"Authorization")->second);
string s = "Basic ";
string::size_type i = authorization.find(s);
if (i != std::string::npos)
authorization.erase(i, s.length());
else
return "";
string decoded = from_base64(authorization);
i = decoded.find(":");
if (i != string::npos && i <= decoded.length())
decoded.erase(i, decoded.length() - i);
else
return "";
return decoded;
}
else
return "";
}
string Server::extractPassword(http_request& request) {
if (request.headers().has(L"Authorization")) {
string authorization = to_string(request.headers().find(L"Authorization")->second);
string s = "Basic ";
string::size_type i = authorization.find(s);
if (i != std::string::npos)
authorization.erase(i, s.length());
else
return "";
string decoded = from_base64(authorization);
i = decoded.find(":");
if (i != string::npos && i+1 < decoded.length())
decoded.erase(0, i+1);
else
return "";
return decoded;
}
else
return "";
}
void Server::task()
{
string address = REST_ADDRESS;
string jsonLocation = instancePath + OLYMPUS_JSON_PATH;
log("Reading configuration from " + jsonLocation);
std::ifstream ifstream(jsonLocation);
std::stringstream ss;
ss << ifstream.rdbuf();
std::error_code errorCode;
json::value config = json::value::parse(ss.str(), errorCode);
if (config.is_object() && config.has_object_field(L"backend") &&
config[L"backend"].has_string_field(L"address") && config[L"backend"].has_number_field(L"port"))
{
address = "http://" + to_string(config[L"backend"][L"address"]) + ":" + to_string(config[L"backend"][L"port"].as_number().to_int32());
log("Starting backend on " + address);
}
else
log("Error reading configuration file. Starting backend on " + address);
if (config.is_object() && config.has_object_field(L"authentication"))
{
if (config[L"authentication"].has_string_field(L"gameMasterPassword")) gameMasterPassword = to_string(config[L"authentication"][L"gameMasterPassword"]);
if (config[L"authentication"].has_string_field(L"blueCommanderPassword")) blueCommanderPassword = to_string(config[L"authentication"][L"blueCommanderPassword"]);
if (config[L"authentication"].has_string_field(L"redCommanderPassword")) redCommanderPassword = to_string(config[L"authentication"][L"redCommanderPassword"]);
}
else
log("Error reading configuration file. No password set.");
http_listener listener(to_wstring(address + "/" + REST_URI));
std::function<void(http_request)> handle_options = std::bind(&Server::handle_options, this, std::placeholders::_1);
std::function<void(http_request)> handle_get = std::bind(&Server::handle_get, this, std::placeholders::_1);
std::function<void(http_request)> handle_put = std::bind(&Server::handle_put, this, std::placeholders::_1);
listener.support(methods::OPTIONS, handle_options);
listener.support(methods::GET, handle_get);
listener.support(methods::PUT, handle_put);
try
{
listener.open()
.then([&listener]() {log("RESTServer starting to listen"); })
.wait();
while (runListener) { Sleep(1000); };
listener.close()
.then([&listener]() {log("RESTServer stopping connections"); })
.wait();
log("RESTServer stopped listening");
}
catch (exception const& e)
{
log(e.what());
}
}

865
backend/core/src/unit.cpp Normal file
View File

@@ -0,0 +1,865 @@
#include "unit.h"
#include "utils.h"
#include "logger.h"
#include "commands.h"
#include "scheduler.h"
#include "defines.h"
#include "unitsmanager.h"
#include <chrono>
using namespace std::chrono;
#include <GeographicLib/Geodesic.hpp>
using namespace GeographicLib;
extern Scheduler* scheduler;
extern UnitsManager* unitsManager;
Unit::Unit(json::value json, unsigned int ID) :
ID(ID)
{
log("Creating unit with ID: " + to_string(ID));
}
Unit::~Unit()
{
}
void Unit::initialize(json::value json)
{
update(json, 0);
setDefaults();
}
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"))
{
setPosition({
json[L"position"][L"lat"].as_number().to_double(),
json[L"position"][L"lng"].as_number().to_double(),
json[L"position"][L"alt"].as_number().to_double()
});
}
if (json.has_number_field(L"heading"))
setHeading(json[L"heading"].as_number().to_double());
if (json.has_number_field(L"track"))
setTrack(json[L"track"].as_number().to_double());
if (json.has_number_field(L"speed"))
setSpeed(json[L"speed"].as_number().to_double());
if (json.has_number_field(L"horizontalVelocity"))
setHorizontalVelocity(json[L"horizontalVelocity"].as_number().to_double());
if (json.has_number_field(L"verticalVelocity"))
setVerticalVelocity(json[L"verticalVelocity"].as_number().to_double());
if (json.has_boolean_field(L"isAlive"))
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"))
setHuman(json[L"isHuman"].as_bool());
if (json.has_number_field(L"fuel")) {
setFuel(short(json[L"fuel"].as_number().to_double() * 100));
}
if (json.has_object_field(L"ammo")) {
vector<DataTypes::Ammo> ammo;
for (auto const& el : json[L"ammo"].as_object()) {
DataTypes::Ammo ammoItem;
auto ammoJson = el.second;
if (ammoJson.has_number_field(L"count"))
ammoItem.quantity = ammoJson[L"count"].as_number().to_uint32();
if (ammoJson.has_object_field(L"desc")) {
if (ammoJson[L"desc"].has_string_field(L"displayName")) {
string name = to_string(ammoJson[L"desc"][L"displayName"].as_string());
name = name.substr(0, min(name.size(), sizeof(ammoItem.name) - 1));
strcpy_s(ammoItem.name, sizeof(ammoItem.name), name.c_str());
}
if (ammoJson[L"desc"].has_number_field(L"guidance"))
ammoItem.guidance = ammoJson[L"desc"][L"guidance"].as_number().to_uint32();
if (ammoJson[L"desc"].has_number_field(L"category"))
ammoItem.category = ammoJson[L"desc"][L"category"].as_number().to_uint32();
if (ammoJson[L"desc"].has_number_field(L"missileCategory"))
ammoItem.missileCategory = ammoJson[L"desc"][L"missileCategory"].as_number().to_uint32();
}
ammo.push_back(ammoItem);
}
setAmmo(ammo);
}
if (json.has_object_field(L"contacts")) {
vector<DataTypes::Contact> contacts;
for (auto const& el : json[L"contacts"].as_object()) {
DataTypes::Contact contactItem;
auto contactJson = el.second;
contactItem.ID = contactJson[L"object"][L"id_"].as_number().to_uint32();
string detectionMethod = to_string(contactJson[L"detectionMethod"]);
if (detectionMethod.compare("VISUAL") == 0) contactItem.detectionMethod = 1;
else if (detectionMethod.compare("OPTIC") == 0) contactItem.detectionMethod = 2;
else if (detectionMethod.compare("RADAR") == 0) contactItem.detectionMethod = 4;
else if (detectionMethod.compare("IRST") == 0) contactItem.detectionMethod = 8;
else if (detectionMethod.compare("RWR") == 0) contactItem.detectionMethod = 16;
else if (detectionMethod.compare("DLINK") == 0) contactItem.detectionMethod = 32;
contacts.push_back(contactItem);
}
setContacts(contacts);
}
if (json.has_boolean_field(L"hasTask"))
setHasTask(json[L"hasTask"].as_bool());
if (json.has_number_field(L"health"))
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();
}
void Unit::setDefaults(bool force)
{
setAlarmState(AlarmState::AUTO, force);
}
void Unit::runAILoop() {
/* Set isLeader */
Unit* leader = nullptr;
setIsLeader(unitsManager->isUnitGroupLeader(this, leader));
/* If the unit is alive, controlled, is the leader of the group and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
if (getAlive() && getControlled() && !getHuman() && getIsLeader()) {
if (getEnableTaskCheckFailed() && checkTaskFailed()) {
log(unitName + " has no task, switching to IDLE state");
setState(State::IDLE);
}
AIloop();
}
refreshLeaderData(lastLoopTime);
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
lastLoopTime = ms.count();
}
void Unit::refreshLeaderData(unsigned long long time) {
/* When units are in a group, most data comes from the group leader. If new data is available, align it from the leader */
if (!getIsLeader()) {
Unit* leader = unitsManager->getGroupLeader(this);
if (leader != nullptr) {
for (unsigned char datumIndex = DataIndex::startOfData + 1; datumIndex < DataIndex::lastIndex; datumIndex++)
{
if (leader->checkFreshness(datumIndex, time)) {
switch (datumIndex) {
case DataIndex::controlled: updateValue(controlled, leader->controlled, datumIndex); break;
case DataIndex::state: updateValue(state, leader->state, datumIndex); break;
case DataIndex::task: updateValue(task, leader->task, datumIndex); break;
case DataIndex::hasTask: updateValue(hasTask, leader->hasTask, datumIndex); break;
case DataIndex::isActiveTanker: updateValue(isActiveTanker, leader->isActiveTanker, datumIndex); break;
case DataIndex::isActiveAWACS: updateValue(isActiveAWACS, leader->isActiveAWACS, datumIndex); break;
case DataIndex::onOff: updateValue(onOff, leader->onOff, datumIndex); break;
case DataIndex::followRoads: updateValue(followRoads, leader->followRoads, datumIndex); break;
case DataIndex::desiredSpeed: updateValue(desiredSpeed, leader->desiredSpeed, datumIndex); break;
case DataIndex::desiredSpeedType: updateValue(desiredSpeedType, leader->desiredSpeedType, datumIndex); break;
case DataIndex::desiredAltitude: updateValue(desiredAltitude, leader->desiredAltitude, datumIndex); break;
case DataIndex::desiredAltitudeType: updateValue(desiredAltitudeType, leader->desiredAltitudeType, datumIndex); break;
case DataIndex::leaderID: updateValue(leaderID, leader->leaderID, datumIndex); break;
case DataIndex::formationOffset: updateValue(formationOffset, leader->formationOffset, datumIndex); break;
case DataIndex::targetID: updateValue(targetID, leader->targetID, datumIndex); break;
case DataIndex::targetPosition: updateValue(targetPosition, leader->targetPosition, datumIndex); break;
case DataIndex::ROE: updateValue(ROE, leader->ROE, datumIndex); break;
case DataIndex::reactionToThreat: updateValue(reactionToThreat, leader->reactionToThreat, datumIndex); break;
case DataIndex::emissionsCountermeasures: updateValue(emissionsCountermeasures, leader->emissionsCountermeasures, datumIndex); break;
case DataIndex::TACAN: updateValue(TACAN, leader->TACAN, datumIndex); break;
case DataIndex::radio: updateValue(radio, leader->radio, datumIndex); break;
case DataIndex::generalSettings: updateValue(generalSettings, leader->generalSettings, datumIndex); break;
case DataIndex::activePath: updateValue(activePath, leader->activePath, datumIndex); break;
case DataIndex::operateAs: updateValue(operateAs, leader->operateAs, datumIndex); break;
case DataIndex::shotsScatter: updateValue(shotsScatter, leader->shotsScatter, datumIndex); break;
case DataIndex::shotsIntensity: updateValue(shotsIntensity, leader->shotsIntensity, datumIndex); break;
case DataIndex::alarmState: updateValue(alarmState, leader->alarmState, datumIndex); break;
}
}
}
}
}
}
bool Unit::checkFreshness(unsigned char datumIndex, unsigned long long time) {
auto it = updateTimeMap.find(datumIndex);
if (it == updateTimeMap.end())
return false;
else
return it->second > time;
}
bool Unit::hasFreshData(unsigned long long time) {
for (auto it : updateTimeMap)
if (it.second > time)
return true;
return false;
}
void Unit::getData(stringstream& ss, unsigned long long time)
{
/* When an update is requested, make sure data is refreshed */
if (time == 0)
refreshLeaderData(0);
const unsigned char endOfData = DataIndex::endOfData;
ss.write((const char*)&ID, sizeof(ID));
if (!alive && time == 0) {
unsigned char datumIndex = DataIndex::category;
appendString(ss, datumIndex, category);
datumIndex = DataIndex::alive;
appendNumeric(ss, datumIndex, alive);
datumIndex = DataIndex::unitID;
appendNumeric(ss, datumIndex, unitID);
}
else {
for (unsigned char datumIndex = DataIndex::startOfData + 1; datumIndex < DataIndex::lastIndex; datumIndex++)
{
if (checkFreshness(datumIndex, time)) {
switch (datumIndex) {
case DataIndex::category: appendString(ss, datumIndex, category); 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::controlled: appendNumeric(ss, datumIndex, controlled); break;
case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break;
case DataIndex::country: appendNumeric(ss, datumIndex, country); break;
case DataIndex::name: appendString(ss, datumIndex, name); 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::state: appendNumeric(ss, datumIndex, state); break;
case DataIndex::task: appendString(ss, datumIndex, task); break;
case DataIndex::hasTask: appendNumeric(ss, datumIndex, hasTask); break;
case DataIndex::position: appendNumeric(ss, datumIndex, position); break;
case DataIndex::speed: appendNumeric(ss, datumIndex, speed); break;
case DataIndex::horizontalVelocity: appendNumeric(ss, datumIndex, horizontalVelocity); break;
case DataIndex::verticalVelocity: appendNumeric(ss, datumIndex, verticalVelocity); break;
case DataIndex::heading: appendNumeric(ss, datumIndex, heading); break;
case DataIndex::track: appendNumeric(ss, datumIndex, track); break;
case DataIndex::isActiveTanker: appendNumeric(ss, datumIndex, isActiveTanker); break;
case DataIndex::isActiveAWACS: appendNumeric(ss, datumIndex, isActiveAWACS); break;
case DataIndex::onOff: appendNumeric(ss, datumIndex, onOff); break;
case DataIndex::followRoads: appendNumeric(ss, datumIndex, followRoads); break;
case DataIndex::fuel: appendNumeric(ss, datumIndex, fuel); break;
case DataIndex::desiredSpeed: appendNumeric(ss, datumIndex, desiredSpeed); break;
case DataIndex::desiredSpeedType: appendNumeric(ss, datumIndex, desiredSpeedType); break;
case DataIndex::desiredAltitude: appendNumeric(ss, datumIndex, desiredAltitude); break;
case DataIndex::desiredAltitudeType: appendNumeric(ss, datumIndex, desiredAltitudeType); break;
case DataIndex::leaderID: appendNumeric(ss, datumIndex, leaderID); break;
case DataIndex::formationOffset: appendNumeric(ss, datumIndex, formationOffset); break;
case DataIndex::targetID: appendNumeric(ss, datumIndex, targetID); break;
case DataIndex::targetPosition: appendNumeric(ss, datumIndex, targetPosition); break;
case DataIndex::ROE: appendNumeric(ss, datumIndex, ROE); break;
case DataIndex::reactionToThreat: appendNumeric(ss, datumIndex, reactionToThreat); break;
case DataIndex::emissionsCountermeasures: appendNumeric(ss, datumIndex, emissionsCountermeasures); break;
case DataIndex::TACAN: appendNumeric(ss, datumIndex, TACAN); break;
case DataIndex::radio: appendNumeric(ss, datumIndex, radio); break;
case DataIndex::generalSettings: appendNumeric(ss, datumIndex, generalSettings); break;
case DataIndex::ammo: appendVector(ss, datumIndex, ammo); break;
case DataIndex::contacts: appendVector(ss, datumIndex, contacts); break;
case DataIndex::activePath: appendList(ss, datumIndex, activePath); break;
case DataIndex::isLeader: appendNumeric(ss, datumIndex, isLeader); break;
case DataIndex::operateAs: appendNumeric(ss, datumIndex, operateAs); break;
case DataIndex::shotsScatter: appendNumeric(ss, datumIndex, shotsScatter); break;
case DataIndex::shotsIntensity: appendNumeric(ss, datumIndex, shotsIntensity); 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;
}
}
}
}
ss.write((const char*)&endOfData, sizeof(endOfData));
}
void Unit::setAmmo(vector<DataTypes::Ammo> newValue)
{
if (ammo.size() == newValue.size()) {
bool equal = true;
for (int i = 0; i < ammo.size(); i++) {
if (ammo.at(i) != newValue.at(i))
{
equal = false;
break;
}
}
if (equal)
return;
}
ammo = newValue;
triggerUpdate(DataIndex::ammo);
}
void Unit::setContacts(vector<DataTypes::Contact> newValue)
{
if (contacts.size() == newValue.size()) {
bool equal = true;
for (int i = 0; i < contacts.size(); i++) {
if (contacts.at(i) != newValue.at(i))
{
equal = false;
break;
}
}
if (equal)
return;
}
contacts = newValue;
triggerUpdate(DataIndex::contacts);
}
void Unit::setActivePath(list<Coords> newPath)
{
activePath = newPath;
resetActiveDestination();
}
void Unit::clearActivePath()
{
list<Coords> newPath;
setActivePath(newPath);
}
void Unit::pushActivePathFront(Coords newActivePathFront)
{
list<Coords> path = activePath;
path.push_front(newActivePathFront);
setActivePath(path);
}
void Unit::pushActivePathBack(Coords newActivePathBack)
{
list<Coords> path = activePath;
path.push_back(newActivePathBack);
setActivePath(path);
}
void Unit::popActivePathFront()
{
list<Coords> path = activePath;
path.pop_front();
setActivePath(path);
}
string Unit::getTargetName()
{
if (isTargetAlive())
{
Unit* target = unitsManager->getUnit(targetID);
if (target != nullptr)
return target->getUnitName();
}
return "";
}
bool Unit::isTargetAlive()
{
if (targetID == NULL)
return false;
Unit* target = unitsManager->getUnit(targetID);
if (target != nullptr)
return target->alive;
else
return false;
}
string Unit::getLeaderName()
{
if (isLeaderAlive())
{
Unit* leader = unitsManager->getUnit(leaderID);
if (leader != nullptr)
return leader->getUnitName();
}
return "";
}
bool Unit::isLeaderAlive()
{
if (leaderID == NULL)
return false;
Unit* leader = unitsManager->getUnit(leaderID);
if (leader != nullptr)
return leader->alive;
else
return false;
}
void Unit::resetActiveDestination()
{
activeDestination = Coords(NULL);
}
void Unit::resetTask()
{
Command* command = dynamic_cast<Command*>(new ResetTask(groupName, [this]() { this->setHasTaskAssigned(false); }));
scheduler->appendCommand(command);
setHasTask(false);
resetTaskFailedCounter();
}
void Unit::setFormationOffset(Offset newFormationOffset)
{
formationOffset = newFormationOffset;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::formationOffset);
}
void Unit::setROE(unsigned char newROE, bool force)
{
if (ROE != newROE || force) {
ROE = newROE;
Command* command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ROE, static_cast<unsigned int>(ROE)));
scheduler->appendCommand(command);
triggerUpdate(DataIndex::ROE);
}
}
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)
{
if (reactionToThreat != newReactionToThreat || force) {
reactionToThreat = newReactionToThreat;
Command* command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::REACTION_ON_THREAT, static_cast<unsigned int>(reactionToThreat)));
scheduler->appendCommand(command);
triggerUpdate(DataIndex::reactionToThreat);
}
}
void Unit::setEmissionsCountermeasures(unsigned char newEmissionsCountermeasures, bool force)
{
if (emissionsCountermeasures != newEmissionsCountermeasures || force) {
emissionsCountermeasures = newEmissionsCountermeasures;
unsigned int radarEnum;
unsigned int flareEnum;
unsigned int ECMEnum;
if (emissionsCountermeasures == EmissionCountermeasure::SILENT)
{
radarEnum = RadarUse::NEVER;
flareEnum = FlareUse::NEVER;
ECMEnum = ECMUse::NEVER_USE;
}
else if (emissionsCountermeasures == EmissionCountermeasure::ATTACK)
{
radarEnum = RadarUse::FOR_ATTACK_ONLY;
flareEnum = FlareUse::AGAINST_FIRED_MISSILE;
ECMEnum = ECMUse::USE_IF_ONLY_LOCK_BY_RADAR;
}
else if (emissionsCountermeasures == EmissionCountermeasure::DEFEND)
{
radarEnum = RadarUse::FOR_SEARCH_IF_REQUIRED;
flareEnum = FlareUse::WHEN_FLYING_IN_SAM_WEZ;
ECMEnum = ECMUse::USE_IF_DETECTED_LOCK_BY_RADAR;
}
else if (emissionsCountermeasures == EmissionCountermeasure::FREE)
{
radarEnum = RadarUse::FOR_CONTINUOUS_SEARCH;
flareEnum = FlareUse::WHEN_FLYING_NEAR_ENEMIES;
ECMEnum = ECMUse::ALWAYS_USE;
}
else
return;
Command* command;
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::RADAR_USING, radarEnum));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::FLARE_USING, flareEnum));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ECM_USING, ECMEnum));
scheduler->appendCommand(command);
triggerUpdate(DataIndex::emissionsCountermeasures);
}
}
void Unit::landAt(Coords loc)
{
clearActivePath();
pushActivePathBack(loc);
setState(State::LAND);
}
void Unit::setIsActiveTanker(bool newIsActiveTanker)
{
if (isActiveTanker != newIsActiveTanker) {
isActiveTanker = newIsActiveTanker;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::isActiveTanker);
}
}
void Unit::setIsActiveAWACS(bool newIsActiveAWACS)
{
if (isActiveAWACS != newIsActiveAWACS) {
isActiveAWACS = newIsActiveAWACS;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::isActiveAWACS);
}
}
void Unit::setTACAN(DataTypes::TACAN newTACAN, bool force)
{
if (TACAN != newTACAN || force)
{
TACAN = newTACAN;
if (TACAN.isOn) {
std::ostringstream commandSS;
if (TACAN.channel < 0)
TACAN.channel = 0;
if (TACAN.channel > 126)
TACAN.channel = 126;
commandSS << "{"
<< "id = 'ActivateBeacon',"
<< "params = {"
<< "type = " << ((TACAN.XY == 'X' == 0) ? 4 : 5) << ","
<< "system = 3,"
<< "name = \"Olympus_TACAN\","
<< "callsign = \"" << TACAN.callsign << "\", "
<< "frequency = " << TACANChannelToFrequency(TACAN.channel, TACAN.XY) << ","
<< "}"
<< "}";
Command* command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
scheduler->appendCommand(command);
}
else {
std::ostringstream commandSS;
commandSS << "{"
<< "id = 'DeactivateBeacon',"
<< "params = {"
<< "}"
<< "}";
Command* command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
scheduler->appendCommand(command);
}
triggerUpdate(DataIndex::TACAN);
}
}
void Unit::setRadio(DataTypes::Radio newRadio, bool force)
{
if (radio != newRadio || force)
{
radio = newRadio;
std::ostringstream commandSS;
Command* command;
if (radio.frequency < 0)
radio.frequency = 0;
if (radio.frequency > 999000000)
radio.frequency = 999000000;
commandSS << "{"
<< "id = 'SetFrequency',"
<< "params = {"
<< "modulation = 0," // TODO Allow selection
<< "frequency = " << radio.frequency << ","
<< "}"
<< "}";
command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
scheduler->appendCommand(command);
// Clear the stringstream
commandSS.str(string(""));
commandSS << "{"
<< "id = 'SetCallsign',"
<< "params = {"
<< "callname = " << to_string(radio.callsign) << ","
<< "number = " << to_string(radio.callsignNumber) << ","
<< "}"
<< "}";
command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
scheduler->appendCommand(command);
triggerUpdate(DataIndex::radio);
}
}
void Unit::setGeneralSettings(DataTypes::GeneralSettings newGeneralSettings, bool force)
{
if (generalSettings != newGeneralSettings)
{
generalSettings = newGeneralSettings;
Command* command;
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::PROHIBIT_AA, generalSettings.prohibitAA));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::PROHIBIT_AG, generalSettings.prohibitAG));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::PROHIBIT_JETT, generalSettings.prohibitJettison));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::PROHIBIT_AB, generalSettings.prohibitAfterburner));
scheduler->appendCommand(command);
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ENGAGE_AIR_WEAPONS, !generalSettings.prohibitAirWpn));
scheduler->appendCommand(command);
triggerUpdate(DataIndex::generalSettings);
}
}
void Unit::setDesiredSpeed(double newDesiredSpeed)
{
if (desiredSpeed != newDesiredSpeed) {
desiredSpeed = newDesiredSpeed;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::desiredSpeed);
}
}
void Unit::setDesiredAltitude(double newDesiredAltitude)
{
if (desiredAltitude != newDesiredAltitude) {
desiredAltitude = newDesiredAltitude;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::desiredAltitude);
}
}
void Unit::setDesiredSpeedType(string newDesiredSpeedType)
{
if (desiredSpeedType != (newDesiredSpeedType.compare("GS") == 0)) {
desiredSpeedType = newDesiredSpeedType.compare("GS") == 0;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::desiredSpeedType);
}
}
void Unit::setDesiredAltitudeType(string newDesiredAltitudeType)
{
if (desiredAltitudeType != (newDesiredAltitudeType.compare("AGL") == 0)) {
desiredAltitudeType = newDesiredAltitudeType.compare("AGL") == 0;
/* Apply the change */
setHasTask(false);
resetTaskFailedCounter();
AIloop();
triggerUpdate(DataIndex::desiredAltitudeType);
}
}
void Unit::goToDestination(string enrouteTask)
{
if (activeDestination != NULL)
{
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType() ? "GS" : "CAS", getDesiredAltitude(), getDesiredAltitudeType() ? "AGL" : "ASL", enrouteTask, getCategory(), getFollowRoads(), [this]() { this->setHasTaskAssigned(true); }));
scheduler->appendCommand(command);
setHasTask(true);
}
}
bool Unit::isDestinationReached(double threshold)
{
if (activeDestination != NULL)
{
/* Check if any unit in the group has reached the point */
for (auto const& p : unitsManager->getGroupMembers(groupName))
{
double dist = 0;
Geodesic::WGS84().Inverse(p->getPosition().lat, p->getPosition().lng, activeDestination.lat, activeDestination.lng, dist);
if (dist < threshold)
{
log(unitName + " destination reached");
return true;
}
else {
return false;
}
}
return false;
}
else
return true;
}
bool Unit::setActiveDestination()
{
if (activePath.size() > 0)
{
activeDestination = activePath.front();
log(unitName + " active destination set to queue front");
triggerUpdate(DataIndex::activePath);
return true;
}
else
{
activeDestination = Coords(0);
log(unitName + " active destination set to NULL");
triggerUpdate(DataIndex::activePath);
return false;
}
}
bool Unit::updateActivePath(bool looping)
{
if (activePath.size() > 0)
{
/* Push the next destination in the queue to the front */
if (looping)
pushActivePathBack(activePath.front());
popActivePathFront();
log(unitName + " active path front popped");
return true;
}
else {
return false;
}
}
void Unit::setHasTask(bool newValue) {
updateValue(hasTask, newValue, DataIndex::hasTask);
}
bool Unit::checkTaskFailed()
{
if (getHasTask())
return false;
else {
if (taskCheckCounter > 0)
taskCheckCounter -= hasTaskAssigned;
return taskCheckCounter == 0;
}
}
void Unit::resetTaskFailedCounter() {
taskCheckCounter = TASK_CHECK_INIT_VALUE;
}
void Unit::setHasTaskAssigned(bool newHasTaskAssigned) {
hasTaskAssigned = newHasTaskAssigned;
if (hasTaskAssigned)
log(unitName + " was assigned a new task");
else
log(unitName + " no task assigned");
}
void Unit::triggerUpdate(unsigned char datumIndex) {
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

@@ -0,0 +1,247 @@
#include "framework.h"
#include "unitsManager.h"
#include "logger.h"
#include "unit.h"
#include "aircraft.h"
#include "helicopter.h"
#include "groundunit.h"
#include "navyunit.h"
#include "weapon.h"
#include "commands.h"
#include "scheduler.h"
#include "defines.h"
#include <GeographicLib/Geodesic.hpp>
using namespace GeographicLib;
#include "base64.hpp"
using namespace base64;
extern Scheduler* scheduler;
UnitsManager::UnitsManager(lua_State* L)
{
LogInfo(L, "Units Manager constructor called successfully");
}
UnitsManager::~UnitsManager()
{
}
Unit* UnitsManager::getUnit(unsigned int ID)
{
if (units.find(ID) == units.end()) {
return nullptr;
}
else {
return units[ID];
}
}
bool UnitsManager::isUnitInGroup(Unit* unit)
{
if (unit != nullptr) {
string groupName = unit->getGroupName();
if (groupName.length() == 0) return false;
for (auto const& p : units)
{
if (p.second->getGroupName().compare(groupName) == 0 && p.second != unit && p.second->getAlive())
return true;
}
}
return false;
}
/* Returns true if unit is group leader. Else, returns false, and leader will be equal to the group leader */
bool UnitsManager::isUnitGroupLeader(Unit* unit, Unit*& leader)
{
if (unit != nullptr) {
leader = getGroupLeader(unit);
return leader == nullptr? false: unit == leader;
}
else
return false;
}
Unit* UnitsManager::getGroupLeader(Unit* unit)
{
if (unit != nullptr) {
string groupName = unit->getGroupName();
if (groupName.length() == 0) return nullptr;
/* Find the first alive unit that has the same groupName */
for (auto const& p : units)
{
if (p.second->getAlive() && p.second->getGroupName().compare(groupName) == 0)
return p.second;
}
}
return nullptr;
}
vector<Unit*> UnitsManager::getGroupMembers(string groupName)
{
vector<Unit*> members;
for (auto const& p : units)
{
if (p.second->getGroupName().compare(groupName) == 0)
members.push_back(p.second);
}
return members;
}
Unit* UnitsManager::getGroupLeader(unsigned int ID)
{
Unit* unit = getUnit(ID);
return getGroupLeader(unit);
}
void UnitsManager::update(json::value& json, double dt)
{
for (auto const& p : json.as_object())
{
unsigned int ID = std::stoi(p.first);
if (units.count(ID) == 0)
{
json::value value = p.second;
if (value.has_string_field(L"category")) {
string category = to_string(value[L"category"].as_string());
if (category.compare("Aircraft") == 0)
units[ID] = dynamic_cast<Unit*>(new Aircraft(p.second, ID));
else if (category.compare("Helicopter") == 0)
units[ID] = dynamic_cast<Unit*>(new Helicopter(p.second, ID));
else if (category.compare("GroundUnit") == 0)
units[ID] = dynamic_cast<Unit*>(new GroundUnit(p.second, ID));
else if (category.compare("NavyUnit") == 0)
units[ID] = dynamic_cast<Unit*>(new NavyUnit(p.second, ID));
/* Initialize the unit if creation was successfull */
if (units.count(ID) != 0) {
units[ID]->update(p.second, dt);
units[ID]->initialize(p.second);
}
}
}
else {
/* Update the unit if present*/
if (units.count(ID) != 0)
units[ID]->update(p.second, dt);
}
}
}
void UnitsManager::runAILoop() {
/* Run the AI Loop on all units */
for (auto const& unit : units)
unit.second->runAILoop();
}
void UnitsManager::getUnitData(stringstream &ss, unsigned long long time)
{
for (auto const& p : units)
p.second->getData(ss, time);
}
void UnitsManager::deleteUnit(unsigned int ID, bool explosion, string explosionType, bool immediate)
{
if (getUnit(ID) != nullptr)
{
Command* command = dynamic_cast<Command*>(new Delete(ID, explosion, explosionType, immediate));
scheduler->appendCommand(command);
}
}
Unit* UnitsManager::getClosestUnit(Unit* unit, unsigned char coalition, vector<string> categories, double &distance, bool airborneOnly) {
Unit* closestUnit = nullptr;
distance = 0;
for (auto const& p : units) {
/* Check if the units category is of the correct type */
bool requestedCategory = false;
for (auto const& category : categories) {
if (p.second->getCategory().compare(category) == 0) {
requestedCategory = true;
break;
}
}
/* 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()) {
/* Check if the unit is airborne */
if (airborneOnly && !p.second->getAirborne())
continue;
/* Compute the distance from the unit to the tested unit */
double dist;
double bearing1;
double bearing2;
Geodesic::WGS84().Inverse(unit->getPosition().lat, unit->getPosition().lng, p.second->getPosition().lat, p.second->getPosition().lng, dist, bearing1, bearing2);
double altDelta = unit->getPosition().alt - p.second->getPosition().alt;
/* If the closest unit has not been assigned yet, assign it to this unit */
if (closestUnit == nullptr)
{
closestUnit = p.second;
distance = sqrt(dist * dist + altDelta * altDelta);
}
else {
/* Check if the unit is closer than the one already selected */
if (dist < distance) {
closestUnit = p.second;
distance = sqrt(dist * dist + altDelta * altDelta);
}
}
}
}
return closestUnit;
}
map<Unit*, double> UnitsManager::getUnitsInRange(Unit* unit, unsigned char coalition, vector<string> categories, double range, bool airborneOnly) {
map<Unit*, double> unitsInRange;
for (auto const& p : units) {
if (airborneOnly && !p.second->getAirborne())
continue;
/* Check if the units category is of the correct type */
bool requestedCategory = false;
for (auto const& category : categories) {
if (p.second->getCategory().compare(category) == 0) {
requestedCategory = true;
break;
}
}
/* 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()) {
/* Compute the distance from the unit to the tested unit */
double dist;
double bearing1;
double bearing2;
Geodesic::WGS84().Inverse(unit->getPosition().lat, unit->getPosition().lng, p.second->getPosition().lat, p.second->getPosition().lng, dist, bearing1, bearing2);
if (dist <= range)
unitsInRange[p.second] = dist;
}
}
return unitsInRange;
}
void UnitsManager::acquireControl(unsigned int ID) {
Unit* leader = getGroupLeader(ID);
if (leader != nullptr) {
if (!leader->getControlled()) {
leader->setControlled(true);
leader->setDefaults(true);
}
}
}
void UnitsManager::loadDatabases() {
Aircraft::loadDatabase(AIRCRAFT_DATABASE_PATH);
Helicopter::loadDatabase(HELICOPTER_DATABASE_PATH);
GroundUnit::loadDatabase(GROUNDUNIT_DATABASE_PATH);
NavyUnit::loadDatabase(NAVYUNIT_DATABASE_PATH);
}

123
backend/core/src/weapon.cpp Normal file
View File

@@ -0,0 +1,123 @@
#include "weapon.h"
#include "utils.h"
#include "logger.h"
#include "commands.h"
#include "scheduler.h"
#include "defines.h"
#include <chrono>
using namespace std::chrono;
Weapon::Weapon(json::value json, unsigned int ID) :
ID(ID)
{
log("Creating weapon with ID: " + to_string(ID));
}
Weapon::~Weapon()
{
}
void Weapon::initialize(json::value json)
{
if (json.has_string_field(L"name"))
setName(to_string(json[L"name"]));
if (json.has_number_field(L"coalitionID"))
setCoalition(json[L"coalitionID"].as_number().to_int32());
update(json, 0);
}
void Weapon::update(json::value json, double dt)
{
if (json.has_object_field(L"position"))
{
setPosition({
json[L"position"][L"lat"].as_number().to_double(),
json[L"position"][L"lng"].as_number().to_double(),
json[L"position"][L"alt"].as_number().to_double()
});
}
if (json.has_number_field(L"heading"))
setHeading(json[L"heading"].as_number().to_double());
if (json.has_number_field(L"speed"))
setSpeed(json[L"speed"].as_number().to_double());
if (json.has_boolean_field(L"isAlive"))
setAlive(json[L"isAlive"].as_bool());
}
bool Weapon::checkFreshness(unsigned char datumIndex, unsigned long long time) {
auto it = updateTimeMap.find(datumIndex);
if (it == updateTimeMap.end())
return false;
else
return it->second > time;
}
bool Weapon::hasFreshData(unsigned long long time) {
for (auto it : updateTimeMap)
if (it.second > time)
return true;
return false;
}
void Weapon::getData(stringstream& ss, unsigned long long time)
{
const unsigned char endOfData = DataIndex::endOfData;
ss.write((const char*)&ID, sizeof(ID));
if (!alive && time == 0) {
unsigned char datumIndex = DataIndex::category;
appendString(ss, datumIndex, category);
datumIndex = DataIndex::alive;
appendNumeric(ss, datumIndex, alive);
}
else {
for (unsigned char datumIndex = DataIndex::startOfData + 1; datumIndex < DataIndex::lastIndex; datumIndex++)
{
if (checkFreshness(datumIndex, time)) {
switch (datumIndex) {
case DataIndex::category: appendString(ss, datumIndex, category); break;
case DataIndex::alive: appendNumeric(ss, datumIndex, alive); break;
case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break;
case DataIndex::name: appendString(ss, datumIndex, name); break;
case DataIndex::position: appendNumeric(ss, datumIndex, position); break;
case DataIndex::speed: appendNumeric(ss, datumIndex, speed); break;
case DataIndex::heading: appendNumeric(ss, datumIndex, heading); break;
}
}
}
}
ss.write((const char*)&endOfData, sizeof(endOfData));
}
void Weapon::triggerUpdate(unsigned char datumIndex) {
updateTimeMap[datumIndex] = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}
/* Missile */
Missile::Missile(json::value json, unsigned int ID) : Weapon(json, ID)
{
log("New Missile created with ID: " + to_string(ID));
setCategory("Missile");
};
/* Bomb */
Bomb::Bomb(json::value json, unsigned int ID) : Weapon(json, ID)
{
log("New Bomb created with ID: " + to_string(ID));
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

@@ -0,0 +1,67 @@
#include "framework.h"
#include "weaponsManager.h"
#include "logger.h"
#include "weapon.h"
#include "scheduler.h"
#include "base64.hpp"
using namespace base64;
WeaponsManager::WeaponsManager(lua_State* L)
{
LogInfo(L, "Weapons Manager constructor called successfully");
}
WeaponsManager::~WeaponsManager()
{
}
Weapon* WeaponsManager::getWeapon(unsigned int ID)
{
if (weapons.find(ID) == weapons.end()) {
return nullptr;
}
else {
return weapons[ID];
}
}
void WeaponsManager::update(json::value& json, double dt)
{
for (auto const& p : json.as_object())
{
unsigned int ID = std::stoi(p.first);
if (weapons.count(ID) == 0)
{
json::value value = p.second;
if (value.has_string_field(L"category")) {
string category = to_string(value[L"category"].as_string());
if (category.compare("Missile") == 0)
weapons[ID] = dynamic_cast<Weapon*>(new Missile(p.second, ID));
else if (category.compare("Bomb") == 0)
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 */
if (weapons.count(ID) != 0) {
weapons[ID]->update(p.second, dt);
weapons[ID]->initialize(p.second);
}
}
}
else {
/* Update the weapon if present*/
if (weapons.count(ID) != 0)
weapons[ID]->update(p.second, dt);
}
}
}
void WeaponsManager::getWeaponData(stringstream& ss, unsigned long long time)
{
for (auto const& p : weapons)
p.second->getData(ss, time);
}

View File

@@ -0,0 +1,110 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Italian (Italy) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Italian (Italy) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "dcstools.dll"
VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "dcstools.dll"
VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "2.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -23,6 +23,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\dcstools.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\luatools\luatools.vcxproj">
@@ -32,6 +33,9 @@
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="dcstools.rc" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
@@ -73,19 +77,23 @@
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir>
<OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -134,6 +142,7 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

View File

@@ -23,5 +23,13 @@
<ClInclude Include="include\dcstools.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="dcstools.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

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

View File

@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by dcstools.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -42,7 +42,7 @@ void LogError(lua_State* L, string message)
Log(L, message, errorLevel);
}
void Log(lua_State* L, string message, int level)
void Log(lua_State* L, string message, unsigned int level)
{
STACK_INIT;
@@ -56,10 +56,9 @@ void Log(lua_State* L, string message, int level)
STACK_CLEAN;
}
map<int, json::value> getAllUnits(lua_State* L)
void getAllUnits(lua_State* L, map<unsigned int, json::value>& unitJSONs)
{
int res = 0;
map<int, json::value> units;
unsigned int res = 0;
STACK_INIT;
@@ -83,18 +82,19 @@ map<int, json::value> getAllUnits(lua_State* L)
lua_pushnil(L);
while (lua_next(L, 2) != 0)
{
int ID = lua_tonumber(L, -2);
units[ID] = luaTableToJSON(L, -1);
unsigned int ID = static_cast<unsigned int>(lua_tonumber(L, -2));
if (unitJSONs.find(ID) == unitJSONs.end())
unitJSONs[ID] = json::value::object();
luaTableToJSON(L, -1, unitJSONs[ID]);
STACK_POP(1)
}
}
exit:
STACK_CLEAN;
return units;
return;
}
int dostring_in(lua_State* L, string target, string command)
{
lua_getglobal(L, "net");
@@ -102,4 +102,10 @@ int dostring_in(lua_State* L, string target, string command)
lua_pushstring(L, target.c_str());
lua_pushstring(L, command.c_str());
return lua_pcall(L, 2, 0, 0);
}
unsigned int TACANChannelToFrequency(unsigned int channel, char XY)
{
unsigned int basef = (XY == 'X' && channel > 63) || (XY == 'Y' && channel < 64) ? 1087 : 961;
return (basef + channel) * 1000000;
}

2579
backend/docs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
#pragma once
#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::wstring& sMessage, bool addToJSON = false);
void DllExport getLogsJSON(json::value& json, unsigned long long time);

View File

@@ -5,9 +5,10 @@
class Logger
{
public:
void log(const string& sMessage);
void log(const wstring& sMessage);
void toJSON(json::value& json, int logsNumber = NULL);
void log(const string& sMessage, bool addToJSON);
void log(const wstring& sMessage, bool addToJSON);
void toJSON(json::value& json, unsigned long long time);
void setDirectory(string newDirPath);
static Logger* GetLogger();
@@ -19,10 +20,12 @@ private:
static const string m_sFileName;
static Logger* m_pThis;
static ofstream m_Logfile;
static std::list<std::string> m_logs;
static std::map<unsigned long long, std::string> m_logs;
static string m_dirPath;
mutex mutexLock;
void Clear();
void Open();
void Close();
};

110
backend/logger/logger.rc Normal file
View File

@@ -0,0 +1,110 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Italian (Italy) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Italian (Italy) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "logger.dll"
VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "logger.dll"
VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "2.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -25,12 +25,16 @@
<ItemGroup>
<ClInclude Include="include\interface.h" />
<ClInclude Include="include\logger.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\utils\utils.vcxproj">
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="logger.rc" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
@@ -72,19 +76,23 @@
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir>
<OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -133,6 +141,7 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

View File

@@ -29,5 +29,13 @@
<ClInclude Include="include\interface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="logger.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

14
backend/logger/resource.h Normal file
View File

@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by logger.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,25 @@
#include "framework.h"
#include "logger.h"
#include "interface.h"
#define LOGGER Logger::GetLogger()
void setLogDirectory(string m_dirPath)
{
LOGGER->setDirectory(m_dirPath);
}
void log(const string& message, bool addToJSON)
{
LOGGER->log(message, addToJSON);
}
void log(const wstring& message, bool addToJSON)
{
LOGGER->log(message, addToJSON);
}
void getLogsJSON(json::value& json, unsigned long long time)
{
LOGGER->toJSON(json, time);
}

View File

@@ -0,0 +1,98 @@
#include "logger.h"
#include "utils.h"
#include "defines.h"
#include <chrono>
using namespace std::chrono;
const string Logger::m_sFileName = LOG_NAME;
Logger* Logger::m_pThis = NULL;
ofstream Logger::m_Logfile;
std::map<unsigned long long, std::string> Logger::m_logs;
std::string Logger::m_dirPath;
Logger::Logger()
{
}
Logger* Logger::GetLogger()
{
if (m_pThis == NULL) {
m_pThis = new Logger();
m_pThis->Clear();
}
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()
{
try {
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()
{
m_Logfile.close();
}
void Logger::toJSON(json::value& json, unsigned long long time)
{
lock_guard<mutex> guard(mutexLock);
/* Loop on the logs in reverse since we are usually only interested in the very last added logs */
auto itr = m_logs.end();
while (itr != m_logs.begin())
{
--itr;
if (itr->first < time) return;
json[to_wstring(itr->first)] = json::value::string(to_wstring(itr->second));
}
}
void Logger::log(const string& message, bool addToJSON)
{
lock_guard<mutex> guard(mutexLock);
Open();
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
m_Logfile << CurrentDateTime() << ":\t";
m_Logfile << message << "\n";
if (addToJSON)
m_logs[static_cast<unsigned long long>(ms.count())] = message;
Close();
}
void Logger::log(const wstring& message, bool addToJSON)
{
lock_guard<mutex> guard(mutexLock);
Open();
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
m_Logfile << CurrentDateTime() << ":\t";
m_Logfile << to_string(message) << "\n";
if (addToJSON)
m_logs[static_cast<unsigned long long>(ms.count())] = to_string(message);
Close();
}

View File

@@ -4,7 +4,8 @@
void DllExport stackUpdate(lua_State* L, int& stackDepth, int initialStack = 0);
void DllExport stackPop(lua_State* L, int popDepth = 1);
void DllExport stackClean(lua_State* L, int stackDepth);
json::value DllExport luaTableToJSON(lua_State* L, int index, bool logKeys = false);
void DllExport luaTableToJSON(lua_State* L, int index, json::value& json, bool logKeys = false);
void DllExport luaLogTableKeys(lua_State* L, int index);
#define STACK_UPDATE stackUpdate(L, stackDepth, initialStack);
#define STACK_INIT int stackDepth = 0; int initialStack = 0; stackUpdate(L, initialStack);

View File

@@ -0,0 +1,110 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Italian (Italy) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Italian (Italy) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "luatools.dll"
VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "luatools.dll"
VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "2.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -60,19 +60,23 @@
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir>
<OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -121,6 +125,7 @@
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -160,6 +165,10 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\luatools.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="luatools.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@@ -23,5 +23,13 @@
<ClInclude Include="include\luatools.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="luatools.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by luatools.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -18,10 +18,31 @@ void stackClean(lua_State* L, int stackDepth)
lua_pop(L, stackDepth);
}
json::value luaTableToJSON(lua_State* L, int index, bool logKeys)
{
auto json = json::value::object();
void luaLogTableKeys(lua_State* L, int index)
{
if (lua_istable(L, index))
{
STACK_INIT;
lua_pushvalue(L, index);
lua_pushnil(L);
while (lua_next(L, -2))
{
lua_pushvalue(L, -2);
const char* key = lua_tostring(L, -1);
log(key);
lua_pop(L, 2);
}
lua_pop(L, 1);
STACK_CLEAN;
}
}
void luaTableToJSON(lua_State* L, int index, json::value& json, bool logKeys)
{
if (lua_istable(L, index))
{
STACK_INIT;
@@ -38,7 +59,9 @@ json::value luaTableToJSON(lua_State* L, int index, bool logKeys)
}
if (lua_istable(L, -2))
{
json[to_wstring(key)] = luaTableToJSON(L, -2, logKeys);
if (!json.has_object_field(to_wstring(key)))
json[to_wstring(key)] = json::value::object();
luaTableToJSON(L, -2, json[to_wstring(key)], logKeys);
}
else if (lua_isnumber(L, -2))
{
@@ -58,6 +81,5 @@ json::value luaTableToJSON(lua_State* L, int index, bool logKeys)
STACK_CLEAN;
}
return json;
}

110
backend/olympus/olympus.rc Normal file
View File

@@ -0,0 +1,110 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Italian (Italy) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Italian (Italy) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "olympus.dll"
VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "olympus.dll"
VALUE "ProductName", "DCS Olympus"
VALUE "ProductVersion", "2.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -20,10 +20,19 @@
<ProjectReference Include="..\logger\logger.vcxproj">
<Project>{873ecabe-fcfe-4217-ac15-91959c3cf1c6}</Project>
</ProjectReference>
<ProjectReference Include="..\luatools\luatools.vcxproj">
<Project>{de139ec1-4f88-47d5-be73-f41915fe14a3}</Project>
</ProjectReference>
<ProjectReference Include="..\utils\utils.vcxproj">
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="olympus.rc" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
@@ -53,9 +62,11 @@
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -64,10 +75,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>.\..\..\bin\</OutDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgAutoLink>true</VcpkgAutoLink>
<OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -87,6 +95,7 @@
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>lua.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
<Version>{{OLYMPUS_VERSION_NUMBER}}.{{OLYMPUS_COMMIT_HASH}}</Version>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -112,6 +121,7 @@
<EnableUAC>false</EnableUAC>
<AdditionalDependencies>lua.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
<DelayLoadDLLs>dcstools.dll;logger.dll;utils.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@@ -13,4 +13,10 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="olympus.rc" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by olympus.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,259 @@
#include "framework.h"
#include "dcstools.h"
#include "logger.h"
#include "utils.h"
/* Run-time linking to core dll allows for "hot swap". This is useful for development but could be removed when stable.*/
HINSTANCE hGetProcIDDLL = NULL;
typedef int(__stdcall* f_coreInit)(lua_State* L, const char* path);
typedef int(__stdcall* f_coreDeinit)(lua_State* L);
typedef int(__stdcall* f_coreFrame)(lua_State* L);
typedef int(__stdcall* f_coreUnitsData)(lua_State* L);
typedef int(__stdcall* f_coreWeaponsData)(lua_State* L);
typedef int(__stdcall* f_coreMissionData)(lua_State* L);
typedef int(__stdcall* f_coreDrawingsData)(lua_State* L);
f_coreInit coreInit = nullptr;
f_coreDeinit coreDeinit = nullptr;
f_coreFrame coreFrame = nullptr;
f_coreUnitsData coreUnitsData = nullptr;
f_coreWeaponsData coreWeaponsData = nullptr;
f_coreMissionData coreMissionData = nullptr;
f_coreDrawingsData coreDrawingsData = nullptr;
string modPath;
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
{
//Get the error message ID, if any.
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0) {
return std::string(); //No error message has been recorded
}
LPSTR messageBuffer = nullptr;
//Ask Win32 to give us the string version of that message ID.
//The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be).
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
//Copy the error message into a std::string.
std::string message(messageBuffer, size);
//Free the Win32's string's buffer.
LocalFree(messageBuffer);
return message;
}
static int onSimulationStart(lua_State* L)
{
LogInfo(L, "Trying to load core.dll from " + modPath);
SetDllDirectoryA(modPath.c_str());
setLogDirectory(modPath);
log("onSimulationStart callback called successfully");
string dllLocation = modPath + "\\core.dll";
log("Loading core.dll");
hGetProcIDDLL = LoadLibrary(to_wstring(dllLocation).c_str());
if (!hGetProcIDDLL) {
LogError(L, "Error loading core DLL");
goto error;
}
log("Core DLL loaded successfully");
coreInit = (f_coreInit)GetProcAddress(hGetProcIDDLL, "coreInit");
if (!coreInit)
{
LogError(L, "Error getting coreInit ProcAddress from DLL");
goto error;
}
coreDeinit = (f_coreDeinit)GetProcAddress(hGetProcIDDLL, "coreDeinit");
if (!coreDeinit)
{
LogError(L, "Error getting coreDeinit ProcAddress from DLL");
goto error;
}
coreFrame = (f_coreFrame)GetProcAddress(hGetProcIDDLL, "coreFrame");
if (!coreFrame)
{
LogError(L, "Error getting coreFrame ProcAddress from DLL");
goto error;
}
coreUnitsData = (f_coreUnitsData)GetProcAddress(hGetProcIDDLL, "coreUnitsData");
if (!coreUnitsData)
{
LogError(L, "Error getting coreUnitsData ProcAddress from DLL");
goto error;
}
coreWeaponsData = (f_coreWeaponsData)GetProcAddress(hGetProcIDDLL, "coreWeaponsData");
if (!coreWeaponsData)
{
LogError(L, "Error getting coreWeaponsData ProcAddress from DLL");
goto error;
}
coreMissionData = (f_coreMissionData)GetProcAddress(hGetProcIDDLL, "coreMissionData");
if (!coreMissionData)
{
LogError(L, "Error getting coreMissionData ProcAddress from DLL");
goto error;
}
coreDrawingsData = (f_coreDrawingsData)GetProcAddress(hGetProcIDDLL, "coreDrawingsData");
if (!coreDrawingsData)
{
LogError(L, "Error getting coreDrawingsData ProcAddress from DLL");
goto error;
}
coreInit(L, modPath.c_str());
LogInfo(L, "Module loaded and started successfully.");
return 0;
error:
LogError(L, "Error while loading module: " + GetLastErrorAsString());
return 0;
}
static int onSimulationFrame(lua_State* L)
{
if (coreFrame)
{
coreFrame(L);
}
return 0;
}
static int onSimulationStop(lua_State* L)
{
log("onSimulationStop callback called successfully");
if (hGetProcIDDLL)
{
log("Trying to unload core DLL");
if (coreDeinit)
{
coreDeinit(L);
}
if (FreeLibrary(hGetProcIDDLL))
{
log("Core DLL unloaded successfully");
}
else
{
LogError(L, "Error unloading DLL");
goto error;
}
coreInit = nullptr;
coreDeinit = nullptr;
coreFrame = nullptr;
coreUnitsData = nullptr;
coreWeaponsData = nullptr;
coreMissionData = nullptr;
coreDrawingsData = nullptr;
}
hGetProcIDDLL = NULL;
return 0;
error:
LogError(L, "Error while unloading module: " + GetLastErrorAsString());
return 0;
}
static int setUnitsData(lua_State* L)
{
if (coreUnitsData)
{
coreUnitsData(L);
}
return 0;
}
static int setWeaponsData(lua_State* L)
{
if (coreWeaponsData)
{
coreWeaponsData(L);
}
return 0;
}
static int setMissionData(lua_State* L)
{
if (coreMissionData)
{
coreMissionData(L);
}
return 0;
}
static int setDrawingsData(lua_State* L)
{
if (coreDrawingsData)
{
coreDrawingsData(L);
}
return 0;
}
static const luaL_Reg Map[] = {
{"onSimulationStart", onSimulationStart},
{"onSimulationFrame", onSimulationFrame},
{"onSimulationStop", onSimulationStop},
{"setUnitsData", setUnitsData },
{"setWeaponsData", setWeaponsData },
{"setMissionData", setMissionData },
{"setDrawingsData", setDrawingsData },
{NULL, NULL}
};
extern "C" DllExport int luaopen_olympus(lua_State * L)
{
lua_getglobal(L, "require");
lua_pushstring(L, "lfs");
lua_pcall(L, 1, 1, 0);
lua_getfield(L, -1, "writedir");
lua_pcall(L, 0, 1, 0);
if (lua_isstring(L, -1)) {
modPath = string(lua_tostring(L, -1)) + "Mods\\Services\\Olympus\\bin\\";
SetDllDirectoryA(modPath.c_str());
LogInfo(L, "Instance location retrieved successfully");
}
else {
/* Log without using the helper dlls because we have not loaded them yet here */
lua_getglobal(L, "log");
lua_getfield(L, -1, "ERROR");
int errorLevel = (int)lua_tointeger(L, -1);
lua_getglobal(L, "log");
lua_getfield(L, -1, "write");
lua_pushstring(L, "Olympus.dll");
lua_pushnumber(L, errorLevel);
lua_pushstring(L, "An error has occurred while trying to retrieve Olympus's instance location");
lua_pcall(L, 3, 0, 0);
return 0;
}
LogInfo(L, "Loading .dlls from " + modPath);
luaL_register(L, "olympus", Map);
return 1;
}

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

@@ -20,6 +20,7 @@
#include <codecvt>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <cpprest/streams.h>
#include <set>
using namespace std;

View File

@@ -1,6 +1,7 @@
#pragma once
#include "framework.h"
#pragma pack(push, 1)
struct Coords {
double lat = 0;
double lng = 0;
@@ -12,20 +13,27 @@ struct Offset {
double y = 0;
double z = 0;
};
#pragma pack(pop)
// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
const DllExport std::string CurrentDateTime();
std::wstring DllExport to_wstring(const std::string& str);
std::string DllExport to_string(json::value& value);
std::string DllExport to_string(const std::wstring& wstr);
std::string DllExport random_string(size_t length);
bool DllExport operator== (const Coords& a, const Coords& b);
bool DllExport operator!= (const Coords& a, const Coords& b);
bool DllExport operator== (const Coords& a, const int& b);
bool DllExport operator!= (const Coords& a, const int& b);
bool DllExport operator== (const Coords& a, const double& b);
bool DllExport operator!= (const Coords& a, const double& b);
bool DllExport operator== (const Offset& a, const Offset& b);
bool DllExport operator!= (const Offset& a, const Offset& b);
bool DllExport operator== (const Offset& a, const int& b);
bool DllExport operator!= (const Offset& a, const int& b);
bool DllExport operator== (const Offset& a, const double& b);
bool DllExport operator!= (const Offset& a, const double& b);
double DllExport knotsToMs(const double knots);
double DllExport msToKnots(const double ms);
double DllExport ftToM(const double ft);
double DllExport mToFt(const double m);

14
backend/utils/resource.h Normal file
View File

@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by utils.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -14,12 +14,16 @@ const std::string CurrentDateTime()
std::wstring to_wstring(const std::string& str)
{
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
unsigned int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (unsigned int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (unsigned int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
std::string to_string(json::value& value) {
return to_string(value.as_string());
}
std::string to_string(const std::wstring& wstr)
{
if (wstr.empty())
@@ -27,19 +31,20 @@ std::string to_string(const std::wstring& wstr)
return "";
}
const auto size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr.at(0), (int)wstr.size(), nullptr, 0, nullptr, nullptr);
const auto size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr.at(0), (unsigned int)wstr.size(), nullptr, 0, nullptr, nullptr);
if (size_needed <= 0)
{
throw std::runtime_error("WideCharToMultiByte() failed: " + std::to_string(size_needed));
}
std::string result(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wstr.at(0), (int)wstr.size(), &result.at(0), size_needed, nullptr, nullptr);
WideCharToMultiByte(CP_UTF8, 0, &wstr.at(0), (unsigned int)wstr.size(), &result.at(0), size_needed, nullptr, nullptr);
return result;
}
std::string random_string(size_t length)
{
srand(static_cast<unsigned int>(time(NULL)));
auto randchar = []() -> char
{
const char charset[] =
@@ -56,10 +61,27 @@ std::string random_string(size_t length)
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 == b); }
bool operator== (const Coords& a, const int& b) { return a.lat == b && a.lng == b && a.alt == b; }
bool operator!= (const Coords& a, const int& 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 == 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 == b); }
bool operator== (const Offset& a, const int& b) { return a.x == b && a.y == b && a.z == b; }
bool operator!= (const Offset& a, const int& b) { return !(a == b); }
bool operator== (const Offset& a, const double& b) { return a.x == b && a.y == b && a.z == b; }
bool operator!= (const Offset& a, const double& b) { return !(a == b); }
double knotsToMs(const double knots) {
return knots / 1.94384;
}
double msToKnots(const double ms) {
return ms * 1.94384;
}
double ftToM(const double ft) {
return ft * 0.3048;
}
double mToFt(const double m) {
return m / 0.3048;
}

110
backend/utils/utils.rc Normal file
View File

@@ -0,0 +1,110 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Italian (Italy) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Italian (Italy) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,0
PRODUCTVERSION 1,0,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "DCS Olympus"
VALUE "FileDescription", "DCS Olympus"
VALUE "FileVersion", "2.0.0.0"
VALUE "InternalName", "utils.dll"
VALUE "LegalCopyright", "Copyright (C) 2023"
VALUE "OriginalFilename", "utils.dll"
VALUE "ProductName", "TODO: <Product name>"
VALUE "ProductVersion", "2.0.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -20,10 +20,14 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\utils.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\utils.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="utils.rc" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
@@ -65,19 +69,23 @@
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<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="..\DCSOlympus.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\..\..\bin\</OutDir>
<OutDir>.\..\..\build\backend\bin\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>.\..\..\bin\$(Platform)\$(Configuration)\</OutDir>

View File

@@ -14,10 +14,16 @@
<ClInclude Include="include\utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="utils.rc" />
</ItemGroup>
</Project>

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"
]
}

2
build_package.bat Normal file
View File

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

View File

@@ -1,30 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Chrome",
"port": 9222,
"urlFilter": "http://localhost:3000/*",
"request": "attach",
"type": "chrome",
"webRoot": "${workspaceFolder}/public/",
"sourceMapPathOverrides": {
"src/*": "${workspaceFolder}/src/*"
}
},
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}/public/",
"sourceMapPathOverrides": {
"src/*": "${workspaceFolder}/src/*"
},
"preLaunchTask": "server"
}
]
}

View File

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

View File

@@ -1,7 +0,0 @@
RTB
tanker
scenario dropdown
explosion
wrong name for ground units
improve map zIndex
human symbol if user

View File

@@ -1,38 +0,0 @@
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var fs = require('fs');
var indexRouter = require('./routes/index');
var uikitRouter = require('./routes/uikit');
var usersRouter = require('./routes/users');
var app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/uikit', uikitRouter);
app.set('view engine', 'ejs');
let rawdata = fs.readFileSync('../olympus.json');
let config = JSON.parse(rawdata);
app.get('/config', (req, res) => res.send(config));
module.exports = app;
const DemoDataGenerator = require('./demo.js');
var demoDataGenerator = new DemoDataGenerator(10);
app.get('/demo/units', (req, res) => demoDataGenerator.units(req, res));
app.get('/demo/logs', (req, res) => demoDataGenerator.logs(req, res));
app.get('/demo/bullseyes', (req, res) => demoDataGenerator.bullseyes(req, res));
app.get('/demo/airbases', (req, res) => demoDataGenerator.airbases(req, res));
app.get('/demo/mission', (req, res) => demoDataGenerator.mission(req, res));

View File

@@ -1,90 +0,0 @@
#!/usr/bin/env node
/**
* 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 port = normalizePort(process.env.PORT || '3000');
app.set('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);
}

View File

@@ -1,2 +0,0 @@
start cmd /k "npm run start"
start cmd /k "watchify .\src\index.ts --debug -p [ tsify --noImplicitAny ] -o .\public\javascripts\bundle.js"

View File

@@ -1,689 +0,0 @@
const DEMO_UNIT_DATA = {
["1"]:{
baseData: {
AI: true,
name: "F-5E",
unitName: "Olympus 1-1",
groupName: "Group 1",
alive: true,
category: "Aircraft",
},
flightData: {
latitude: 37.20,
longitude: -115.80,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 50,
flags: {human: false},
ammo: [
{
count: 4,
desc: {
displayName: "AIM-120"
}
},
{
count: 2,
desc: {
displayName: "AIM-7"
}
}
],
targets: [],
hasTask: true,
coalition: "blue"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Holding",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "Designated",
reactionToThreat: "Abort",
}
},
["2"]:{
baseData: {
AI: true,
name: "F-5E",
unitName: "Olympus 1-2",
groupName: "Group 1",
alive: true,
category: "Aircraft",
},
flightData: {
latitude: 37.2,
longitude: -115.75,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "red"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 300,
targetAltitude: 3000
},
optionsData: {
ROE: "Designated",
reactionToThreat: "Abort",
}
},
["3"]:{
baseData: {
AI: true,
name: "2S6 Tunguska",
unitName: "Olympus 1-3",
groupName: "Group 1",
alive: true,
category: "GroundUnit",
},
flightData: {
latitude: 37.175,
longitude: -115.8,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "blue"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["4"]:{
baseData: {
AI: true,
name: "2S6 Tunguska",
unitName: "Olympus 1-4",
groupName: "Group 1",
alive: true,
category: "GroundUnit",
},
flightData: {
latitude: 37.175,
longitude: -115.75,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "red"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["5"]:{
baseData: {
AI: true,
name: "M-60",
unitName: "Olympus 1-3",
groupName: "Group 1",
alive: true,
category: "GroundUnit",
},
flightData: {
latitude: 37.15,
longitude: -115.8,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "blue"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["6"]:{
baseData: {
AI: true,
name: "M-60",
unitName: "Olympus 1-4",
groupName: "Group 1",
alive: true,
category: "GroundUnit",
},
flightData: {
latitude: 37.15,
longitude: -115.75,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "red"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["7"]:{
baseData: {
AI: true,
name: "CVN-75",
unitName: "Olympus 1-7",
groupName: "Group 1",
alive: true,
category: "NavyUnit",
},
flightData: {
latitude: 37.125,
longitude: -115.8,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "blue"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["8"]:{
baseData: {
AI: true,
name: "CVN-75",
unitName: "Olympus 1-8",
groupName: "Group 1",
alive: true,
category: "NavyUnit",
},
flightData: {
latitude: 37.125,
longitude: -115.75,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "red"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["9"]:{
baseData: {
AI: true,
name: "CVN-75",
unitName: "Olympus 1-9",
groupName: "Group 1",
alive: true,
category: "Aircraft",
},
flightData: {
latitude: 37.10,
longitude: -115.75,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "red"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["10"]:{
baseData: {
AI: true,
name: "CVN-75",
unitName: "Olympus 1-10",
groupName: "Group 1",
alive: true,
category: "Aircraft",
},
flightData: {
latitude: 37.10,
longitude: -115.8,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "blue"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["11"]:{
baseData: {
AI: true,
name: "CVN-75",
unitName: "Olympus 1-11",
groupName: "Group 1",
alive: true,
category: "Missile",
},
flightData: {
latitude: 37.075,
longitude: -115.80,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "blue"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["12"]:{
baseData: {
AI: true,
name: "CVN-75",
unitName: "Olympus 1-12",
groupName: "Group 1",
alive: true,
category: "Missile",
},
flightData: {
latitude: 37.075,
longitude: -115.75,
altitude: 2000,
heading: 0.6,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "red"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["13"]:{
baseData: {
AI: true,
name: "CVN-75",
unitName: "Olympus 1-11",
groupName: "Group 1",
alive: true,
category: "Bomb",
},
flightData: {
latitude: 37.05,
longitude: -115.8,
altitude: 2000,
heading: 0.5,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "blue"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
},
["14"]:{
baseData: {
AI: true,
name: "CVN-75",
unitName: "Olympus 1-12",
groupName: "Group 1",
alive: true,
category: "Bomb",
},
flightData: {
latitude: 37.05,
longitude: -115.75,
altitude: 2000,
heading: 0.6,
speed: 300
},
missionData: {
fuel: 0.5,
flags: {human: false},
ammo: [],
targets: [],
hasTask: true,
coalition: "red"
},
formationData: {
formation: "Echelon",
isLeader: false,
isWingman: false,
leaderID: null,
wingmen: [],
wingmenIDs: []
},
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
},
optionsData: {
ROE: "None",
reactionToThreat: "None",
}
}
}
class DemoDataGenerator {
constructor(unitsNumber)
{
this.demoUnits = this.generateRandomUnitsDemoData(unitsNumber);
}
units(req, res){
var ret = this.demoUnits;
res.send(JSON.stringify(ret));
};
logs(req, res){
var ret = {logs: {}};
res.send(JSON.stringify(ret));
};
airbases(req, res){
var ret = {airbases: {
["0"]: {
callsign: "Neutral",
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"
}
}};
res.send(JSON.stringify(ret));
};
bullseyes(req, res){
var ret = {bullseyes: {
"0": {
latitude: 37.25,
longitude: -115.8
},
"1": {
latitude: 37.25,
longitude: -115.75
},
"2": {
latitude: 37.25,
longitude: -115.7
}
}};
res.send(JSON.stringify(ret));
};
mission(req, res){
var ret = {mission: {theatre: "Nevada"}};
res.send(JSON.stringify(ret));
}
generateRandomUnitsDemoData(unitsNumber)
{
return {"units": DEMO_UNIT_DATA};
}
}
module.exports = DemoDataGenerator;

5848
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +0,0 @@
{
"name": "DCSOlympus",
"node-main": "./bin/www",
"main": "http://localhost:3000",
"version": "0.1.1-alpha",
"private": true,
"scripts": {
"copy": "copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet.css",
"start": "npm run copy & concurrently --kill-others \"npm run watch\" \"nodemon ./bin/www\"",
"watch": "watchify .\\src\\index.ts --debug -p [ tsify --noImplicitAny ] -o .\\public\\javascripts\\bundle.js"
},
"dependencies": {
"@types/geojson": "^7946.0.10",
"@types/leaflet": "^1.9.0",
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"ejs": "^3.1.8",
"express": "~4.16.1",
"leaflet": "^1.9.3",
"milsymbol": "^2.0.0",
"morgan": "~1.9.1",
"save": "^2.9.0"
},
"devDependencies": {
"@types/gtag.js": "^0.0.12",
"@types/sortablejs": "^1.15.0",
"browserify": "^17.0.0",
"concurrently": "^7.6.0",
"nodemon": "^2.0.20",
"sortablejs": "^1.15.0",
"tsify": "^5.0.4",
"typescript": "^4.9.4",
"watchify": "^4.0.0"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -1,3 +0,0 @@
<svg width="15" height="14" viewBox="0 0 15 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.4766 9.25718L11.3099 8.44468C11.4401 8.31772 11.6667 8.40659 11.6667 8.58941V12.2812C11.6667 12.9541 11.1068 13.5 10.4167 13.5H1.25C0.559896 13.5 0 12.9541 0 12.2812V3.3437C0 2.67085 0.559896 2.12495 1.25 2.12495H8.3724C8.55729 2.12495 8.65104 2.34331 8.52083 2.4728L7.6875 3.2853C7.64844 3.32339 7.59635 3.3437 7.53906 3.3437H1.25V12.2812H10.4167V9.39937C10.4167 9.34605 10.4375 9.29526 10.4766 9.25718ZM14.5547 4.13335L7.71615 10.8009L5.36198 11.0548C4.67969 11.1285 4.09896 10.5673 4.17448 9.89702L4.4349 7.60171L11.2734 0.934131C11.8698 0.352686 12.8333 0.352686 13.4271 0.934131L14.5521 2.03101C15.1484 2.61245 15.1484 3.55444 14.5547 4.13335ZM11.9818 4.91792L10.4688 3.44272L5.63021 8.16284L5.4401 9.82085L7.14063 9.6355L11.9818 4.91792ZM13.6693 2.89429L12.5443 1.79741C12.4375 1.69331 12.263 1.69331 12.1589 1.79741L11.3542 2.58198L12.8672 4.05718L13.6719 3.27261C13.776 3.16597 13.776 2.99839 13.6693 2.89429Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="96.000000pt" height="96.000000pt" viewBox="0 0 96.000000 96.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,96.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M411 846 c-77 -78 -70 -86 69 -86 139 0 146 8 69 86 -29 30 -60 54
-69 54 -9 0 -40 -24 -69 -54z"/>
<path d="M132 668 c-16 -16 -15 -43 2 -57 9 -8 110 -11 351 -9 309 3 339 4
349 21 8 12 8 22 0 35 -10 16 -40 17 -350 20 -256 2 -343 -1 -352 -10z"/>
<path d="M132 508 c-16 -16 -15 -43 2 -57 9 -8 110 -11 351 -9 309 3 339 4
349 21 8 12 8 22 0 35 -10 16 -40 17 -350 20 -256 2 -343 -1 -352 -10z"/>
<path d="M132 348 c-16 -16 -15 -43 2 -57 9 -8 110 -11 351 -9 309 3 339 4
349 21 8 12 8 22 0 35 -10 16 -40 17 -350 20 -256 2 -343 -1 -352 -10z"/>
<path d="M363 184 c-7 -18 92 -124 117 -124 25 0 124 106 117 124 -9 24 -225
24 -234 0z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

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