//------------------------------------------------------------------------------ // // SimConnect AI Objects sample // // Description: // Adds Non ATC controlled simulation objects. // Launch a flight from KSEA - Runway 34R // and watch the antics. // Press z to create the objects // Press x to load them with their waypoint lists // Press c to remove the generated objects //------------------------------------------------------------------------------ #include #include #include #include #include "SimConnect.h" int quit = 0; HANDLE hSimConnect = NULL; DWORD PittsID = SIMCONNECT_OBJECT_ID_USER; DWORD DA62ID = SIMCONNECT_OBJECT_ID_USER; DWORD TruckID = SIMCONNECT_OBJECT_ID_USER; DWORD GiraffeID = SIMCONNECT_OBJECT_ID_USER; static enum EVENT_ID { EVENT_SIM_START, EVENT_Z, EVENT_X, EVENT_C }; static enum DATA_REQUEST_ID { REQUEST_ADD_DA62, REQUEST_ADD_PITTS, REQUEST_ADD_GIRAFFE, REQUEST_ADD_TRUCK, REQUEST_REMOVE_DA62, REQUEST_REMOVE_PITTS, REQUEST_REMOVE_GIRAFFE, REQUEST_REMOVE_TRUCK }; static enum GROUP_ID { GROUP_ZX, }; static enum INPUT_ID { INPUT_ZX, }; static enum DEFINITION_ID { DEFINITION_WAYPOINT }; // Set up flags so these operations only happen once static bool plansSent = false; static bool objectsCreated = false; void sendFlightPlans() { HRESULT hr; SIMCONNECT_DATA_WAYPOINT waypointListDA62[3]; // DA62 waypoint list SIMCONNECT_DATA_WAYPOINT waypointListTruck[2]; // Truck waypoint list SIMCONNECT_DATA_WAYPOINT waypointListGiraffe[2]; // Giraffe waypoint list // DA62 aircraft should fly in circles across the North end of the runway waypointListDA62[0].Flags = SIMCONNECT_WAYPOINT_SPEED_REQUESTED; waypointListDA62[0].Altitude = 800; waypointListDA62[0].Latitude = 47 + (27.79 / 60); waypointListDA62[0].Longitude = -122 - (18.46 / 60); waypointListDA62[0].ktsSpeed = 100; waypointListDA62[1].Flags = SIMCONNECT_WAYPOINT_SPEED_REQUESTED; waypointListDA62[1].Altitude = 600; waypointListDA62[1].Latitude = 47 + (27.79 / 60); waypointListDA62[1].Longitude = -122 - (17.37 / 60); waypointListDA62[1].ktsSpeed = 100; waypointListDA62[2].Flags = SIMCONNECT_WAYPOINT_WRAP_TO_FIRST | SIMCONNECT_WAYPOINT_SPEED_REQUESTED; waypointListDA62[2].Altitude = 800; waypointListDA62[2].Latitude = 47 + (27.79 / 60); waypointListDA62[2].Longitude = -122 - (19.92 / 60); waypointListDA62[2].ktsSpeed = 100; // Send the three waypoints to the DA62 hr = SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_WAYPOINT, DA62ID, 0, ARRAYSIZE(waypointListDA62), sizeof(waypointListDA62[0]), waypointListDA62); // Truck goes down the runway waypointListTruck[0].Flags = SIMCONNECT_WAYPOINT_SPEED_REQUESTED; waypointListTruck[0].Altitude = 433; waypointListTruck[0].Latitude = 47 + (25.95 / 60); waypointListTruck[0].Longitude = -122 - (18.47 / 60); waypointListTruck[0].ktsSpeed = 75; waypointListTruck[1].Flags = SIMCONNECT_WAYPOINT_WRAP_TO_FIRST | SIMCONNECT_WAYPOINT_SPEED_REQUESTED; waypointListTruck[1].Altitude = 433; waypointListTruck[1].Latitude = 47 + (26.25 / 60); waypointListTruck[1].Longitude = -122 - (18.46 / 60); waypointListTruck[1].ktsSpeed = 55; // Send the two waypoints to the truck hr = SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_WAYPOINT, TruckID, 0, ARRAYSIZE(waypointListTruck), sizeof(waypointListTruck[0]), waypointListTruck); // Giraffe walks in circles left to the user aircraft waypointListGiraffe[0].Flags = SIMCONNECT_WAYPOINT_SPEED_REQUESTED; waypointListGiraffe[0].Altitude = 433; waypointListGiraffe[0].Latitude = 47 + (25.96 / 60); waypointListGiraffe[0].Longitude = -122 - (18.52 / 60); waypointListGiraffe[0].ktsSpeed = 5; waypointListGiraffe[1].Flags = SIMCONNECT_WAYPOINT_WRAP_TO_FIRST | SIMCONNECT_WAYPOINT_SPEED_REQUESTED; waypointListGiraffe[1].Altitude = 433; waypointListGiraffe[1].Latitude = 47 + (25.98 / 60); waypointListGiraffe[1].Longitude = -122 - (18.55 / 60); waypointListGiraffe[1].ktsSpeed = 5; // Send the two waypoints to the giraffe hr = SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_WAYPOINT, GiraffeID, 0, ARRAYSIZE(waypointListGiraffe), sizeof(waypointListGiraffe[0]), waypointListGiraffe); } void setUpSimObjects() { SIMCONNECT_DATA_INITPOSITION Init; HRESULT hr; // Add a parked "Aviat Pitts Special S2S" aircraft, just west of the runway Init.Altitude = 433.0; // Altitude of Sea-tac is 433 feet Init.Latitude = 47 + (25.96 / 60); // Convert from 47 25.96 N Init.Longitude = -122 - (18.51 / 60); // Convert from 122 18.51 W Init.Pitch = 0.0; Init.Bank = 0.0; Init.Heading = 0.0; Init.OnGround = 1; Init.Airspeed = 0; hr = SimConnect_AICreateSimulatedObject(hSimConnect, "Aviat Pitts S2", Init, REQUEST_ADD_PITTS); // Initialize DA62 aircraft just in front of user aircraft Init.Altitude = 433.0; // Altitude of Sea-tac is 433 feet Init.Latitude = 47 + (25.95 / 60); // Convert from 47 25.95 N Init.Longitude = -122 - (18.48 / 60); // Convert from 122 18.48 W Init.Pitch = 0.0; Init.Bank = 0.0; Init.Heading = 360.0; Init.OnGround = 1; Init.Airspeed = 1; hr = SimConnect_AICreateNonATCAircraft(hSimConnect, "DA62 Passengers", "N1001", Init, REQUEST_ADD_DA62); // Initialize truck in front and to the right of user aircraft Init.Altitude = 433.0; // Altitude of Sea-tac is 433 feet Init.Latitude = 47 + (25.95 / 60); // Convert from 47 25.95 N Init.Longitude = -122 - (18.47 / 60); // Convert from 122 18.47 W Init.Pitch = 0.0; Init.Bank = 0.0; Init.Heading = 360.0; Init.OnGround = 1; Init.Airspeed = 0; hr = SimConnect_AICreateSimulatedObject(hSimConnect, "ASO_Firetruck02", Init, REQUEST_ADD_TRUCK); // Add a giraffe to the left of the user aircraft, next to the trees Init.Altitude = 433.0; // Altitude of Sea-tac is 433 feet Init.Latitude = 47 + (25.96 / 60); // Convert from 47 25.96 N Init.Longitude = -122 - (18.52 / 60); // Convert from 122 18.52 W Init.Pitch = 0.0; Init.Bank = 0.0; Init.Heading = 0.0; Init.OnGround = 1; Init.Airspeed = 0; hr = SimConnect_AICreateSimulatedObject(hSimConnect, "GGiraffaFemale", Init, REQUEST_ADD_GIRAFFE); } void removeSimObjects() { HRESULT hr; if (PittsID != SIMCONNECT_OBJECT_ID_USER) { hr = SimConnect_AIRemoveObject(hSimConnect, PittsID,REQUEST_REMOVE_PITTS); } if (DA62ID != SIMCONNECT_OBJECT_ID_USER) { hr = SimConnect_AIRemoveObject(hSimConnect, DA62ID, REQUEST_REMOVE_DA62); } if (TruckID != SIMCONNECT_OBJECT_ID_USER) { hr = SimConnect_AIRemoveObject(hSimConnect, TruckID, REQUEST_REMOVE_TRUCK); } if (GiraffeID != SIMCONNECT_OBJECT_ID_USER) { hr = SimConnect_AIRemoveObject(hSimConnect, GiraffeID, REQUEST_REMOVE_GIRAFFE); } } static const char* ExceptionName(SIMCONNECT_EXCEPTION exception) { switch (exception) { case SIMCONNECT_EXCEPTION_NONE: //0 return "EXCEPTION_NONE (0)"; case SIMCONNECT_EXCEPTION_ERROR: //1 return "EXCEPTION_ERROR (1)"; case SIMCONNECT_EXCEPTION_SIZE_MISMATCH: //2 return "EXCEPTION_SIZE_MISMATCH (2)"; case SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID: //3 return "EXCEPTION_UNRECOGNIZED_ID (3)"; case SIMCONNECT_EXCEPTION_UNOPENED: //4 return "EXCEPTION_UNOPENED (4)"; case SIMCONNECT_EXCEPTION_VERSION_MISMATCH: //5 return "EXCEPTION_VERSION_MISMATCH (5)"; case SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS: //6 return "EXCEPTION_TOO_MANY_GROUPS (6)"; case SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED://7 return "EXCEPTION_NAME_UNRECOGNIZED (7)"; case SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES: //8 return "EXCEPTION_TOO_MANY_EVENT_NAMES (8)"; case SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE: //9 return "EXCEPTION_EVENT_ID_DUPLICATE (9)"; case SIMCONNECT_EXCEPTION_TOO_MANY_MAPS: //10 return "EXCEPTION_TOO_MANY_MAPS (10)"; case SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS: //11 return "EXCEPTION_TOO_MANY_OBJECTS (11)"; case SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS: //12 return "EXCEPTION_TOO_MANY_REQUESTS (12)"; case SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT: //13 return "EXCEPTION_WEATHER_INVALID_PORT (13)"; case SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR: //14 return "EXCEPTION_WEATHER_INVALID_METAR (14)"; case SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION://15 return "EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION (15)"; case SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION: //16 return "EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION (16)"; case SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION: //17 return "EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION (17)"; case SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE: //18 return "EXCEPTION_INVALID_DATA_TYPE (18)"; case SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE: //19 return "EXCEPTION_INVALID_DATA_SIZE (19)"; case SIMCONNECT_EXCEPTION_DATA_ERROR: //20 return "EXCEPTION_DATA_ERROR (20)"; case SIMCONNECT_EXCEPTION_INVALID_ARRAY: //21 return "EXCEPTION_INVALID_ARRAY (21)"; case SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED: //22 return "EXCEPTION_CREATE_OBJECT_FAILED (22)"; case SIMCONNECT_EXCEPTION_LOAD_FLIGHTPLAN_FAILED: //23 return "EXCEPTION_LOAD_FLIGHTPLAN_FAILED (23)"; case SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE://24 return "EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE (24)"; case SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION: //25 return "EXCEPTION_ILLEGAL_OPERATION (25)"; case SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED: //26 return "EXCEPTION_ALREADY_SUBSCRIBED (26)"; case SIMCONNECT_EXCEPTION_INVALID_ENUM: //27 return "EXCEPTION_INVALID_ENUM (27)"; case SIMCONNECT_EXCEPTION_DEFINITION_ERROR: //28 return "EXCEPTION_DEFINITION_ERROR (28)"; case SIMCONNECT_EXCEPTION_DUPLICATE_ID: //29 return "EXCEPTION_DUPLICATE_ID (29)"; case SIMCONNECT_EXCEPTION_DATUM_ID: //30 return "EXCEPTION_DATUM_ID (30)"; case SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS: //31 return "EXCEPTION_OUT_OF_BOUNDS (31)"; case SIMCONNECT_EXCEPTION_ALREADY_CREATED: //32 return "EXCEPTION_ALREADY_CREATED (32)"; case SIMCONNECT_EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE://33 return "EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE (33)"; case SIMCONNECT_EXCEPTION_OBJECT_CONTAINER: //34 return "EXCEPTION_OBJECT_CONTAINER (34)"; case SIMCONNECT_EXCEPTION_OBJECT_AI: //35 return "EXCEPTION_OBJECT_AI (35)"; case SIMCONNECT_EXCEPTION_OBJECT_ATC: //36 return "EXCEPTION_OBJECT_ATC (36)"; case SIMCONNECT_EXCEPTION_OBJECT_SCHEDULE: //37 return "EXCEPTION_OBJECT_SCHEDULE (37)"; default: return "UNKNOWN EXCEPTION"; } } void CALLBACK MyDispatchProcSO(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext) { HRESULT hr; switch (pData->dwID) { case SIMCONNECT_RECV_ID_EVENT: { SIMCONNECT_RECV_EVENT* evt = (SIMCONNECT_RECV_EVENT*)pData; switch (evt->uEventID) { case EVENT_Z: if (!objectsCreated) { setUpSimObjects(); objectsCreated = true; printf("\nPress 'x' to change the flight plans"); } break; case EVENT_X: if (!plansSent && objectsCreated) { sendFlightPlans(); plansSent = true; } break; case EVENT_C: if (objectsCreated) { removeSimObjects(); objectsCreated = false; plansSent = false; } break; default: printf("\nUnknown event: %d", evt->uEventID); break; } break; } case SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID: { SIMCONNECT_RECV_ASSIGNED_OBJECT_ID* pObjData = (SIMCONNECT_RECV_ASSIGNED_OBJECT_ID*)pData; switch (pObjData->dwRequestID) { case REQUEST_ADD_DA62: DA62ID = pObjData->dwObjectID; printf("\nCreated DA62 id = %d", DA62ID); break; case REQUEST_ADD_PITTS: PittsID = pObjData->dwObjectID; printf("\nCreated stationary Aviat Pitts Special S2S id = %d", pObjData->dwObjectID); break; case REQUEST_ADD_TRUCK: TruckID = pObjData->dwObjectID; printf("\nCreated truck id = %d", TruckID); break; case REQUEST_ADD_GIRAFFE: GiraffeID = pObjData->dwObjectID; printf("\nCreated giraffe id = %d", GiraffeID); break; default: printf("\nUnknown creation %d", pObjData->dwRequestID); break; } break; } case SIMCONNECT_RECV_ID_QUIT: { quit = 1; break; } case SIMCONNECT_RECV_ID_EXCEPTION: { SIMCONNECT_RECV_EXCEPTION* data = (SIMCONNECT_RECV_EXCEPTION*)(pData); SIMCONNECT_EXCEPTION exception = (SIMCONNECT_EXCEPTION)(data->dwException); printf("\nException: %s", ExceptionName(exception)); break; } default: printf("\nReceived:%d", pData->dwID); break; } } void testSimObjects() { HRESULT hr; if (SUCCEEDED(SimConnect_Open(&hSimConnect, "AI Objects and Waypoints", NULL, 0, 0, 0))) { printf("\nConnected to Flight Simulator!"); // Create some private events hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_Z); hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_X); hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_C); // Link the private events to keyboard keys, and ensure the input events are off hr = SimConnect_MapInputEventToClientEvent(hSimConnect, INPUT_ZX, "Z", EVENT_Z); hr = SimConnect_MapInputEventToClientEvent(hSimConnect, INPUT_ZX, "X", EVENT_X); hr = SimConnect_MapInputEventToClientEvent(hSimConnect, INPUT_ZX, "C", EVENT_C); hr = SimConnect_SetInputGroupState(hSimConnect, INPUT_ZX, SIMCONNECT_STATE_OFF); // Sign up for notifications hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP_ZX, EVENT_Z); hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP_ZX, EVENT_X); hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP_ZX, EVENT_C); // Set up a definition for a waypoint list hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_WAYPOINT, "AI Waypoint List", "number", SIMCONNECT_DATATYPE_WAYPOINT); hr = SimConnect_SetInputGroupState(hSimConnect, INPUT_ZX, SIMCONNECT_STATE_ON); printf("\nPress 'z' to create the aircrafts"); printf("\nLaunch a flight."); while (0 == quit) { SimConnect_CallDispatch(hSimConnect, MyDispatchProcSO, NULL); Sleep(1); } hr = SimConnect_Close(hSimConnect); } } int __cdecl _tmain(int argc, _TCHAR* argv[]) { testSimObjects(); return 0; }