#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <cmath>
#include "SimConnect.h"
#define M_PI 3.14159265358979323846
int quit = 0;
HANDLE hSimConnect = NULL;
DWORD LostPilotID = SIMCONNECT_OBJECT_ID_USER;
enum EVENT_ID {
EVENT_Z = 1, // Spawn Lost_Pilot
EVENT_X = 2, // Refresh position and sweet spot status
EVENT_UPDATE_EMPTY_VISIBILITY = 3, // Set Sling_Empty_Visibility
EVENT_UPDATE_LOADED_VISIBILITY = 4 // Set External_Pilot_Connected
};
enum REQUEST_ID {
REQUEST_USER_POSITION = 1,
};
// Struct to hold the spawn location
struct Position {
double latitude;
double longitude;
double altitude;
};
Position spawnPosition = { 0.0, 0.0, 0.0 };
// Function to calculate distance (nautical miles) between two points
double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
constexpr double earthRadiusNM = 3440.065; // Earth radius in nautical miles
double lat1Rad = lat1 * M_PI / 180.0;
double lon1Rad = lon1 * M_PI / 180.0;
double lat2Rad = lat2 * M_PI / 180.0;
double lon2Rad = lon2 * M_PI / 180.0;
double dLat = lat2Rad - lat1Rad;
double dLon = lon2Rad - lon1Rad;
double a = sin(dLat / 2) * sin(dLat / 2) +
cos(lat1Rad) * cos(lat2Rad) * sin(dLon / 2) * sin(dLon / 2);
double c = 2 * atan2(sqrt(a), sqrt(1 - a));
return earthRadiusNM * c;
}
void setUpLostPilot(double latitude, double longitude, double altitude) {
SIMCONNECT_DATA_INITPOSITION Init;
HRESULT hr;
Init.Altitude = 0.0; // Ground level
Init.Latitude = latitude + (1.0 / 60.0); // Adjust for spawn location
Init.Longitude = longitude + (1.0 / (cos(latitude * M_PI / 180.0) * 60.0));
Init.Pitch = 0.0;
Init.Bank = 0.0;
Init.Heading = 0.0;
Init.OnGround = 1;
Init.Airspeed = 0;
spawnPosition.latitude = Init.Latitude;
spawnPosition.longitude = Init.Longitude;
spawnPosition.altitude = Init.Altitude;
printf("Spawning Lost_Pilot at Lat: %f, Lon: %f, Alt: %f\n", Init.Latitude, Init.Longitude, Init.Altitude);
hr = SimConnect_AICreateSimulatedObject(hSimConnect, "Lost_Pilot", Init, 0);
if (FAILED(hr)) {
printf("Failed to spawn Lost_Pilot. HRESULT: %ld\n", hr);
}
}
void monitorDistance(double userLatitude, double userLongitude, double userAltitude) {
double distance = calculateDistance(userLatitude, userLongitude, spawnPosition.latitude, spawnPosition.longitude);
printf("Distance to Lost_Pilot: %.2f NM\n", distance);
printf("User altitude: %.2f feet\n", userAltitude);
printf("Spawn Position: Lat: %f, Lon: %f, Alt: %f\n", spawnPosition.latitude, spawnPosition.longitude, spawnPosition.altitude);
bool withinDistance = (distance <= 0.0033); // Approximately 20 feet
bool withinAltitude = (userAltitude >= 90.0 && userAltitude <= 210.0);
if (withinDistance && withinAltitude) {
printf("Aircraft is within the sweet spot. Updating LVars and removing Lost_Pilot...\n");
// Remove Lost_Pilot object
HRESULT hrRemove = SimConnect_AIRemoveObject(hSimConnect, LostPilotID, 0);
if (SUCCEEDED(hrRemove)) {
printf("Lost_Pilot removed successfully.\n");
LostPilotID = SIMCONNECT_OBJECT_ID_USER; // Reset the ID
}
else {
printf("Failed to remove Lost_Pilot. HRESULT: %ld\n", hrRemove);
}
// Update LVars
HRESULT hrEmptyVisibility = SimConnect_TransmitClientEvent(
hSimConnect,
SIMCONNECT_OBJECT_ID_USER,
EVENT_UPDATE_EMPTY_VISIBILITY, // Event defined to set Sling_Empty_Visibility
0, // Value to set: 0
SIMCONNECT_GROUP_PRIORITY_HIGHEST,
SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY
);
HRESULT hrLoadedVisibility = SimConnect_TransmitClientEvent(
hSimConnect,
SIMCONNECT_OBJECT_ID_USER,
EVENT_UPDATE_LOADED_VISIBILITY, // Event defined to set External_Pilot_Connected
1, // Value to set: 1
SIMCONNECT_GROUP_PRIORITY_HIGHEST,
SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY
);
if (SUCCEEDED(hrEmptyVisibility) && SUCCEEDED(hrLoadedVisibility)) {
printf("LVars updated: Sling_Empty_Visibility set to 0, External_Pilot_Connected set to 1.\n");
}
else {
printf("Failed to update one or more LVars.\n");
if (FAILED(hrEmptyVisibility)) {
printf("Sling_Empty_Visibility update failed. HRESULT: %ld\n", hrEmptyVisibility);
}
if (FAILED(hrLoadedVisibility)) {
printf("External_Pilot_Connected update failed. HRESULT: %ld\n", hrLoadedVisibility);
}
}
}
else {
printf("Aircraft is not in the sweet spot. No updates made.\n");
}
}
void CALLBACK MyDispatchProcSO(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext) {
switch (pData->dwID) {
case SIMCONNECT_RECV_ID_EVENT: {
SIMCONNECT_RECV_EVENT* evt = (SIMCONNECT_RECV_EVENT*)pData;
if (evt->uEventID == EVENT_Z) {
printf("Spawning Lost_Pilot...\n");
// Request user position for spawn
HRESULT hr = SimConnect_RequestDataOnSimObject(
hSimConnect,
REQUEST_USER_POSITION,
REQUEST_USER_POSITION,
SIMCONNECT_OBJECT_ID_USER,
SIMCONNECT_PERIOD_ONCE,
0, 0, 0, 0
);
if (FAILED(hr)) {
printf("Failed to request user position for spawn. HRESULT: %ld\n", hr);
}
}
else if (evt->uEventID == EVENT_X) {
printf("Refreshing position and sweet spot status...\n");
// Request user position for distance calculation
HRESULT hr = SimConnect_RequestDataOnSimObject(
hSimConnect,
REQUEST_USER_POSITION,
REQUEST_USER_POSITION,
SIMCONNECT_OBJECT_ID_USER,
SIMCONNECT_PERIOD_ONCE,
0, 0, 0, 0
);
if (FAILED(hr)) {
printf("Failed to request user position for refresh. HRESULT: %ld\n", hr);
}
}
break;
}
case SIMCONNECT_RECV_ID_SIMOBJECT_DATA: {
SIMCONNECT_RECV_SIMOBJECT_DATA* pObjData = (SIMCONNECT_RECV_SIMOBJECT_DATA*)pData;
if (pObjData->dwRequestID == REQUEST_USER_POSITION) {
double* userData = (double*)&pObjData->dwData;
double userLatitude = userData[0];
double userLongitude = userData[1];
double userAltitude = userData[2];
printf("User position: Lat: %f, Lon: %f, Alt: %f\n", userLatitude, userLongitude, userAltitude);
if (LostPilotID == SIMCONNECT_OBJECT_ID_USER) {
setUpLostPilot(userLatitude, userLongitude, 0.0);
}
else {
monitorDistance(userLatitude, userLongitude, userAltitude);
}
}
break;
}
case SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID: {
SIMCONNECT_RECV_ASSIGNED_OBJECT_ID* pObjData = (SIMCONNECT_RECV_ASSIGNED_OBJECT_ID*)pData;
LostPilotID = pObjData->dwObjectID;
printf("Created Lost_Pilot ID: %d\n", LostPilotID);
break;
}
case SIMCONNECT_RECV_ID_QUIT:
quit = 1;
break;
default:
printf("Unhandled Data ID: %d\n", pData->dwID);
break;
}
}
void testLostPilotSpawn() {
HRESULT hr;
if (SUCCEEDED(SimConnect_Open(&hSimConnect, "Lost_Pilot Spawn Test", NULL, 0, 0, 0))) {
printf("Connected to Flight Simulator!\n");
// Map Z and X events
hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_Z);
hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_X);
// Add client events
hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, 0, EVENT_Z);
hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, 0, EVENT_X);
// Register custom visibility events
hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_UPDATE_EMPTY_VISIBILITY, "CUSTOM_EVENT_SlingEmpty");
hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_UPDATE_LOADED_VISIBILITY, "CUSTOM_EVENT_SlingLoaded");
// Enable input for Z and X keys
hr = SimConnect_MapInputEventToClientEvent(hSimConnect, 0, "Z", EVENT_Z);
hr = SimConnect_MapInputEventToClientEvent(hSimConnect, 0, "X", EVENT_X);
hr = SimConnect_SetInputGroupState(hSimConnect, 0, SIMCONNECT_STATE_ON);
// Define data request
hr = SimConnect_AddToDataDefinition(hSimConnect, REQUEST_USER_POSITION, "PLANE LATITUDE", "degrees");
hr = SimConnect_AddToDataDefinition(hSimConnect, REQUEST_USER_POSITION, "PLANE LONGITUDE", "degrees");
hr = SimConnect_AddToDataDefinition(hSimConnect, REQUEST_USER_POSITION, "PLANE ALTITUDE", "feet");
printf("Press 'Z' to spawn Lost_Pilot.\n");
printf("Press 'X' to refresh position and sweet spot status.\n");
while (0 == quit) {
SimConnect_CallDispatch(hSimConnect, MyDispatchProcSO, NULL);
Sleep(1);
}
hr = SimConnect_Close(hSimConnect);
}
else {
printf("Failed to connect to Flight Simulator.\n");
}
}
int __cdecl _tmain(int argc, _TCHAR* argv[]) {
testLostPilotSpawn();
return 0;
}