Share via


Sample: AIObjects.cpp

//------------------------------------------------------------------------------
//
//  SimConnect AI Objects sample
// 
//    Description:
//                Adds Non ATC controlled simulation objects.
//                With the default flight (Cessna at Seatac) - turn off the engine
//                and watch the antics.
//                Press z to create the objects
//                Press x to load them with their waypoint lists
//------------------------------------------------------------------------------

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

#include "SimConnect.h"

int     quit = 0;
HANDLE  hSimConnect = NULL;
DWORD    BalloonID    = SIMCONNECT_OBJECT_ID_USER;
DWORD    BellID        = SIMCONNECT_OBJECT_ID_USER;
DWORD    MooneyID    = SIMCONNECT_OBJECT_ID_USER;
DWORD    TruckID        = SIMCONNECT_OBJECT_ID_USER;

static enum EVENT_ID {
    EVENT_SIM_START,
    EVENT_Z,
    EVENT_X,
    EVENT_C,
    EVENT_V,
};

static enum DATA_REQUEST_ID7 {
    REQUEST_BALLOON1,
    REQUEST_BELL,
    REQUEST_MOONEY,
    REQUEST_DOUGLAS,
    REQUEST_TRUCK,
    REQUEST_WHALE,
};

static enum GROUP_ID {
    GROUP_ZX,
};

static enum INPUT_ID {
    INPUT_ZX,
};

static enum DEFINITION_ID {
    DEFINITION_WAYPOINT,
    DEFINITION_THROTTLE
};

struct structBalloonControl 
{
    double throttlePercent;
};

structBalloonControl        bc;

// Set up flags so these operations only happen once
static bool plansSent        = false;
static bool    objectsCreated    = false;

void sendFlightPlans()
{
    HRESULT hr;
    SIMCONNECT_DATA_WAYPOINT    wp[3];    // Mooney waypoint list
    SIMCONNECT_DATA_WAYPOINT    ft[2];    // Truck waypoint list

    // Mooney aircraft should fly in circles across the North end of the runway

    wp[0].Flags        = SIMCONNECT_WAYPOINT_SPEED_REQUESTED;
    wp[0].Altitude    = 800;
    wp[0].Latitude    = 47 + (27.79/60);    
    wp[0].Longitude = -122 - (18.46/60);
    wp[0].ktsSpeed    = 100;

    wp[1].Flags        = SIMCONNECT_WAYPOINT_SPEED_REQUESTED;
    wp[1].Altitude    = 600;
    wp[1].Latitude    = 47 + (27.79/60);    
    wp[1].Longitude = -122 - (17.37/60);
    wp[1].ktsSpeed    = 100;

    wp[2].Flags        = SIMCONNECT_WAYPOINT_WRAP_TO_FIRST | SIMCONNECT_WAYPOINT_SPEED_REQUESTED;
    wp[2].Altitude    = 800;
    wp[2].Latitude    = 47 + (27.79/60);    
    wp[2].Longitude = -122 - (19.92/60);
    wp[2].ktsSpeed    = 100;

    // Send the three waypoints to the Mooney
    hr = SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_WAYPOINT, MooneyID, 0, ARRAYSIZE(wp), sizeof(wp[0]), wp);

    // Truck goes down the runway
    ft[0].Flags        = SIMCONNECT_WAYPOINT_SPEED_REQUESTED;
    ft[0].Altitude    = 433;
    ft[0].Latitude    = 47 + (25.93/60);    
    ft[0].Longitude = -122 - (18.46/60);
    ft[0].ktsSpeed    = 75;

    ft[1].Flags        = SIMCONNECT_WAYPOINT_WRAP_TO_FIRST | SIMCONNECT_WAYPOINT_SPEED_REQUESTED;
    ft[1].Altitude    = 433;
    ft[1].Latitude    = 47 + (26.25/60);    
    ft[1].Longitude = -122 - (18.46/60);
    ft[1].ktsSpeed    = 55;

    // Send the two waypoints to the truck
    hr = SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_WAYPOINT, TruckID, 0, ARRAYSIZE(ft), sizeof(ft[0]), ft);


}

void setUpSimObjects()
{
    SIMCONNECT_DATA_INITPOSITION Init;
    HRESULT hr;

    // Add a parked museum aircraft, just west of the runway

    Init.Altitude   = 433.0;                // Altitude of Sea-tac is 433 feet
    Init.Latitude   = 47 + (25.97/60);        // Convert from 47 25.97 N
    Init.Longitude  = -122 - (18.51/60);    // Convert from 122 18.51 W
    Init.Pitch      =  0.0;
    Init.Bank       =  0.0;
    Init.Heading    = 90.0;
    Init.OnGround   = 1;
    Init.Airspeed    = 0;
    hr = SimConnect_AICreateSimulatedObject(hSimConnect, "Douglas DC-3", Init, REQUEST_DOUGLAS);

    // Add a hot air balloon

    Init.Altitude   = 500.0;                // Altitude of Sea-tac is 433 feet
    Init.Latitude   = 47 + (25.97/60);        // Convert from 47 26.22 N
    Init.Longitude  = -122 - (18.45/60);    // Convert from 122 18.45 W
    Init.Pitch      =  0.0;
    Init.Bank       =  0.0;
    Init.Heading    = 0.0;
    Init.OnGround   = 0;
    Init.Airspeed    = 0;
    hr = SimConnect_AICreateSimulatedObject(hSimConnect, "Hot_Air_Balloon", Init, REQUEST_BALLOON1);

    // Add a helicopter

    Init.Altitude   = 433.0;                // Altitude of Sea-tac is 433 feet
    Init.Latitude   = 47 + (26.22/60);        // Convert from 47 26.22 N
    Init.Longitude  = -122 - (18.48/60);    // Convert from 122 18.48 W
    Init.Pitch      =  0.0;
    Init.Bank       =  0.0;
    Init.Heading    = 0.0;
    Init.OnGround   = 1;
    Init.Airspeed    = 100;
    
    //hr = SimConnect_AICreateNonATCAircraft(hSimConnect, "Bell 206B JetRanger", "H1000", Init, REQUEST_BELL);
    
    // Initialize Mooney aircraft just in front of user aircraft
    // User aircraft is at 47 25.89 N, 122 18.48 W

    Init.Altitude   = 433.0;                // Altitude of Sea-tac is 433 feet
    Init.Latitude   = 47 + (25.91/60);        // Convert from 47 25.90 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, "Mooney Bravo", "N1001", Init, REQUEST_MOONEY);
    
    // Initialize truck just in front of user aircraft
    // User aircraft is at 47 25.89 N, 122 18.48 W

    Init.Altitude   = 433.0;                // Altitude of Sea-tac is 433 feet
    Init.Latitude   = 47 + (25.91/60);        // Convert from 47 25.90 N
    Init.Longitude  = -122 - (18.47/60);    // Convert from 122 18.48 W
    Init.Pitch      =  0.0;
    Init.Bank       =  0.0;
    Init.Heading    = 360.0;
    Init.OnGround   = 1;
    Init.Airspeed    = 0;
    
    hr = SimConnect_AICreateSimulatedObject(hSimConnect, "VEH_jetTruck", Init, REQUEST_TRUCK);
    
    // Add a humpback whale

    Init.Altitude   = 433.0;                // Altitude of Sea-tac is 433 feet
    Init.Latitude   = 47 + (25.89/60);        // Convert from 47 25.89 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, "Humpbackwhale", Init, REQUEST_WHALE);
}

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_SIM_START:

                    // Sim has started so turn the input events on
                    hr = SimConnect_SetInputGroupState(hSimConnect, INPUT_ZX, SIMCONNECT_STATE_ON);

                    break;

                case EVENT_Z:
                    if (!objectsCreated)
                    {
                        setUpSimObjects();
                        objectsCreated = true;
                    }
                    break;

                case EVENT_X:
                    if (!plansSent && objectsCreated)
                    {
                        sendFlightPlans();
                        plansSent = true;
                    }
                    break;

                case EVENT_C:
                    {

                        // Give the balloon some throttle
                        if (bc.throttlePercent < 100.0f)
                            bc.throttlePercent    += 5.0f;

                        hr = SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_THROTTLE, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(bc), &bc;);

                        break;
                    }

                case EVENT_V:
                    {

                        // Give the balloon some throttle
                        if (bc.throttlePercent > 0.0f)
                            bc.throttlePercent    -= 5.0f;

                        hr = SimConnect_SetDataOnSimObject(hSimConnect, DEFINITION_THROTTLE, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(bc), &bc;);

                        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_BALLOON1:
                BalloonID = pObjData->dwObjectID;
                printf("\nCreated Balloon 1 id = %d", BalloonID);
                break;

            case REQUEST_BELL:
                BellID = pObjData->dwObjectID;
                printf("\nCreated Bell Helicopter id = %d", BellID);
                break;    
            
            case REQUEST_MOONEY:
                MooneyID = pObjData->dwObjectID;
                printf("\nCreated Mooney Bravo id = %d", MooneyID);
                break;    

            case REQUEST_DOUGLAS:
                printf("\nCreated stationary Douglas DC3 id = %d", pObjData->dwObjectID);
                break;

            case REQUEST_TRUCK:
                TruckID = pObjData->dwObjectID;
                printf("\nCreated truck id = %d", TruckID);
                break;
            
            case REQUEST_WHALE:
                printf("\nCreated humpback whale id = %d", pObjData->dwObjectID);
                break;
            
            default:
                printf("\nUnknown creation %d", pObjData->dwRequestID);
                break;

            }
            break;
        }

        case SIMCONNECT_RECV_ID_QUIT:
        {
            quit = 1;
            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...!");   
          
        // Create some private events
        hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_Z);
        hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_X);
        hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_C);
        hr = SimConnect_MapClientEventToSimEvent(hSimConnect, EVENT_V);


        // 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_MapInputEventToClientEvent(hSimConnect, INPUT_ZX, "V", EVENT_V);

        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);
        hr = SimConnect_AddClientEventToNotificationGroup(hSimConnect, GROUP_ZX, EVENT_V);

        // Set up a definition for a waypoint list
        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_WAYPOINT,
            "AI Waypoint List", "number", SIMCONNECT_DATATYPE_WAYPOINT);

        // Set up a definition for the balloon throttle
        bc.throttlePercent = 0.0f;

        hr = SimConnect_AddToDataDefinition(hSimConnect, DEFINITION_THROTTLE,
            "GENERAL ENG THROTTLE LEVER POSITION:1", "percent");

        // Request a simulation start event
        hr = SimConnect_SubscribeToSystemEvent(hSimConnect, EVENT_SIM_START, "SimStart");

        while( 0 == quit )
        {
            SimConnect_CallDispatch(hSimConnect, MyDispatchProcSO, NULL);
            Sleep(1);
        } 

        hr = SimConnect_Close(hSimConnect);
    }
}


int __cdecl _tmain(int argc, _TCHAR* argv[])
{
    testSimObjects();
    return 0;
}