예제 #1
0
        public static pCarsAPIStruct MergeWithExistingState(pCarsAPIStruct existingState, sTelemetryData udpTelemetryData)
        {
            existingState.hasNewPositionData = false;
            existingState.mGameState         = (uint)udpTelemetryData.sGameSessionState & 7;
            existingState.mSessionState      = (uint)udpTelemetryData.sGameSessionState >> 4;
            existingState.mRaceState         = (uint)udpTelemetryData.sRaceStateFlags & 7;

            // Participant Info
            existingState.mViewedParticipantIndex = udpTelemetryData.sViewedParticipantIndex;
            existingState.mNumParticipants        = udpTelemetryData.sNumParticipants;

            // Unfiltered Input
            existingState.mUnfilteredThrottle = (float)udpTelemetryData.sUnfilteredThrottle / 255f;
            existingState.mUnfilteredBrake    = (float)udpTelemetryData.sUnfilteredBrake / 255f;
            existingState.mUnfilteredSteering = (float)udpTelemetryData.sUnfilteredSteering / 127f;
            existingState.mUnfilteredClutch   = (float)udpTelemetryData.sUnfilteredClutch / 255f;

            existingState.mLapsInEvent = udpTelemetryData.sLapsInEvent;
            existingState.mTrackLength = udpTelemetryData.sTrackLength;

            // Timing & Scoring
            existingState.mLapInvalidated             = (udpTelemetryData.sRaceStateFlags >> 3 & 1) == 1;
            existingState.mSessionFastestLapTime      = udpTelemetryData.sBestLapTime;
            existingState.mLastLapTime                = udpTelemetryData.sLastLapTime;
            existingState.mCurrentTime                = udpTelemetryData.sCurrentTime;
            existingState.mSplitTimeAhead             = udpTelemetryData.sSplitTimeAhead;
            existingState.mSplitTimeBehind            = udpTelemetryData.sSplitTimeBehind;
            existingState.mSplitTime                  = udpTelemetryData.sSplitTime;
            existingState.mEventTimeRemaining         = udpTelemetryData.sEventTimeRemaining;
            existingState.mPersonalFastestLapTime     = udpTelemetryData.sPersonalFastestLapTime;
            existingState.mWorldFastestLapTime        = udpTelemetryData.sWorldFastestLapTime;
            existingState.mCurrentSector1Time         = udpTelemetryData.sCurrentSector1Time;
            existingState.mCurrentSector2Time         = udpTelemetryData.sCurrentSector2Time;
            existingState.mCurrentSector3Time         = udpTelemetryData.sCurrentSector3Time;
            existingState.mSessionFastestSector1Time  = udpTelemetryData.sFastestSector1Time;
            existingState.mSessionFastestSector2Time  = udpTelemetryData.sFastestSector2Time;
            existingState.mSessionFastestSector3Time  = udpTelemetryData.sFastestSector3Time;
            existingState.mPersonalFastestSector1Time = udpTelemetryData.sPersonalFastestSector1Time;
            existingState.mPersonalFastestSector2Time = udpTelemetryData.sPersonalFastestSector2Time;
            existingState.mPersonalFastestSector3Time = udpTelemetryData.sPersonalFastestSector3Time;
            existingState.mWorldFastestSector1Time    = udpTelemetryData.sWorldFastestSector1Time;
            existingState.mWorldFastestSector2Time    = udpTelemetryData.sWorldFastestSector2Time;
            existingState.mWorldFastestSector3Time    = udpTelemetryData.sWorldFastestSector3Time;

            // Flags
            existingState.mHighestFlagColour = (uint)udpTelemetryData.sHighestFlag & 7;
            existingState.mHighestFlagReason = (uint)udpTelemetryData.sHighestFlag >> 3 & 3;

            // Pit Info
            existingState.mPitMode     = (uint)udpTelemetryData.sPitModeSchedule & 7;
            existingState.mPitSchedule = (uint)udpTelemetryData.sPitModeSchedule >> 3 & 3;

            // Car State
            existingState.mCarFlags         = udpTelemetryData.sCarFlags;
            existingState.mOilTempCelsius   = udpTelemetryData.sOilTempCelsius;
            existingState.mOilPressureKPa   = udpTelemetryData.sOilPressureKPa;
            existingState.mWaterTempCelsius = udpTelemetryData.sWaterTempCelsius;
            existingState.mWaterPressureKPa = udpTelemetryData.sWaterPressureKpa;
            existingState.mFuelPressureKPa  = udpTelemetryData.sFuelPressureKpa;
            existingState.mFuelLevel        = udpTelemetryData.sFuelLevel;
            existingState.mFuelCapacity     = udpTelemetryData.sFuelCapacity;
            existingState.mSpeed            = udpTelemetryData.sSpeed;
            existingState.mRPM            = udpTelemetryData.sRpm;
            existingState.mMaxRPM         = udpTelemetryData.sMaxRpm;
            existingState.mBrake          = (float)udpTelemetryData.sBrake / 255f;
            existingState.mThrottle       = (float)udpTelemetryData.sThrottle / 255f;
            existingState.mClutch         = (float)udpTelemetryData.sClutch / 255f;
            existingState.mSteering       = (float)udpTelemetryData.sSteering / 127f;
            existingState.mGear           = udpTelemetryData.sGearNumGears & 15;
            existingState.mNumGears       = udpTelemetryData.sGearNumGears >> 4;
            existingState.mOdometerKM     = udpTelemetryData.sOdometerKM;
            existingState.mAntiLockActive = (udpTelemetryData.sRaceStateFlags >> 4 & 1) == 1;
            existingState.mBoostActive    = (udpTelemetryData.sRaceStateFlags >> 5 & 1) == 1;
            existingState.mBoostAmount    = udpTelemetryData.sBoostAmount;

            // Motion & Device Related
            existingState.mOrientation       = udpTelemetryData.sOrientation;
            existingState.mLocalVelocity     = udpTelemetryData.sLocalVelocity;
            existingState.mWorldVelocity     = udpTelemetryData.sWorldVelocity;
            existingState.mAngularVelocity   = udpTelemetryData.sAngularVelocity;
            existingState.mLocalAcceleration = udpTelemetryData.sLocalAcceleration;
            existingState.mWorldAcceleration = udpTelemetryData.sWorldAcceleration;
            existingState.mExtentsCentre     = udpTelemetryData.sExtentsCentre;


            existingState.mTyreFlags             = toUIntArray(udpTelemetryData.sTyreFlags);
            existingState.mTerrain               = toUIntArray(udpTelemetryData.sTerrain);
            existingState.mTyreY                 = udpTelemetryData.sTyreY;
            existingState.mTyreRPS               = udpTelemetryData.sTyreRPS;
            existingState.mTyreSlipSpeed         = udpTelemetryData.sTyreSlipSpeed;
            existingState.mTyreTemp              = toFloatArray(udpTelemetryData.sTyreTemp, 255);
            existingState.mTyreGrip              = toFloatArray(udpTelemetryData.sTyreGrip, 255);
            existingState.mTyreHeightAboveGround = udpTelemetryData.sTyreHeightAboveGround;
            existingState.mTyreLateralStiffness  = udpTelemetryData.sTyreLateralStiffness;
            existingState.mTyreWear              = toFloatArray(udpTelemetryData.sTyreWear, 255);
            existingState.mBrakeDamage           = toFloatArray(udpTelemetryData.sBrakeDamage, 255);
            existingState.mSuspensionDamage      = toFloatArray(udpTelemetryData.sSuspensionDamage, 255);
            existingState.mBrakeTempCelsius      = toFloatArray(udpTelemetryData.sBrakeTempCelsius, 1);
            existingState.mTyreTreadTemp         = toFloatArray(udpTelemetryData.sTyreTreadTemp, 1);
            existingState.mTyreLayerTemp         = toFloatArray(udpTelemetryData.sTyreLayerTemp, 1);
            existingState.mTyreCarcassTemp       = toFloatArray(udpTelemetryData.sTyreCarcassTemp, 1);
            existingState.mTyreRimTemp           = toFloatArray(udpTelemetryData.sTyreRimTemp, 1);
            existingState.mTyreInternalAirTemp   = toFloatArray(udpTelemetryData.sTyreInternalAirTemp, 1);
            existingState.mWheelLocalPosition    = udpTelemetryData.sWheelLocalPositionY;
            existingState.mRideHeight            = udpTelemetryData.sRideHeight;
            existingState.mSuspensionTravel      = udpTelemetryData.sSuspensionTravel;
            existingState.mSuspensionVelocity    = udpTelemetryData.sSuspensionVelocity;
            existingState.mAirPressure           = toFloatArray(udpTelemetryData.sAirPressure, 1);

            existingState.mEngineSpeed        = udpTelemetryData.sEngineSpeed;
            existingState.mEngineTorque       = udpTelemetryData.sEngineTorque;
            existingState.mEnforcedPitStopLap = (uint)udpTelemetryData.sEnforcedPitStopLap;

            // Car Damage
            existingState.mCrashState   = udpTelemetryData.sCrashState;
            existingState.mAeroDamage   = (float)udpTelemetryData.sAeroDamage / 255f;
            existingState.mEngineDamage = (float)udpTelemetryData.sEngineDamage / 255f;

            // Weather
            existingState.mAmbientTemperature = udpTelemetryData.sAmbientTemperature;
            existingState.mTrackTemperature   = udpTelemetryData.sTrackTemperature;
            existingState.mRainDensity        = (float)udpTelemetryData.sRainDensity / 255f;
            existingState.mWindSpeed          = udpTelemetryData.sWindSpeed * 2;
            existingState.mWindDirectionX     = (float)udpTelemetryData.sWindDirectionX / 127f;
            existingState.mWindDirectionY     = (float)udpTelemetryData.sWindDirectionY / 127f;
            //existingState.mCloudBrightness = udpTelemetryData.sCloudBrightness / 255;

            if (existingState.mParticipantData == null)
            {
                existingState.mParticipantData = new pCarsAPIParticipantStruct[udpTelemetryData.sParticipantInfo.Count()];
            }
            for (int i = 0; i < udpTelemetryData.sParticipantInfo.Count(); i++)
            {
                sParticipantInfo          newPartInfo      = udpTelemetryData.sParticipantInfo[i];
                Boolean                   isActive         = (newPartInfo.sRacePosition >> 7) == 1;
                pCarsAPIParticipantStruct existingPartInfo = existingState.mParticipantData[i];
                existingPartInfo.mIsActive = isActive;
                if (isActive)
                {
                    existingPartInfo.mCurrentLap         = newPartInfo.sCurrentLap;
                    existingPartInfo.mCurrentLapDistance = newPartInfo.sCurrentLapDistance;
                    existingPartInfo.mLapsCompleted      = (uint)newPartInfo.sLapsCompleted & 127;
                    // TODO: there's a 'lapInvalidated' flag here but nowhere to put it in the existing struct
                    Boolean lapInvalidated = (newPartInfo.sLapsCompleted >> 7) == 1;
                    existingPartInfo.mRacePosition  = (uint)newPartInfo.sRacePosition & 127;
                    existingPartInfo.mCurrentSector = (uint)newPartInfo.sSector & 7;

                    // and now the bit magic for the extra position precision...
                    float[] newWorldPositions = toFloatArray(newPartInfo.sWorldPosition, 1);
                    float   xAdjustment       = ((float)((uint)newPartInfo.sSector >> 3 & 3)) / 4f;
                    float   zAdjustment       = ((float)((uint)newPartInfo.sSector >> 5 & 3)) / 4f;
                    newWorldPositions[0] = newWorldPositions[0] + xAdjustment;
                    newWorldPositions[2] = newWorldPositions[2] + zAdjustment;
                    if (!existingState.hasNewPositionData && i != udpTelemetryData.sViewedParticipantIndex &&
                        (existingPartInfo.mWorldPosition == null || (newWorldPositions[0] != existingPartInfo.mWorldPosition[0] || newWorldPositions[2] != existingPartInfo.mWorldPosition[2])))
                    {
                        existingState.hasNewPositionData = true;
                    }
                    existingPartInfo.mWorldPosition = newWorldPositions;

                    // TODO: LastSectorTime is now in the UDP data, but there's no slot for this in the participants struct
                    // existingPartInfo.mLastSectorTime = newPartInfo.sLastSectorTime;
                }
                else
                {
                    existingPartInfo.mWorldPosition = new float[] { 0, 0, 0 };
                }
                existingState.mParticipantData[i] = existingPartInfo;
            }

            // TODO: buttons
            return(existingState);
        }
 private OpponentData createOpponentData(pCarsAPIParticipantStruct participantStruct, Boolean loadDriverName)
 {
     OpponentData opponentData = new OpponentData();
     opponentData.DriverRawName = participantStruct.mName.Trim();
     if (loadDriverName && CrewChief.enableDriverNames)
     {
         speechRecogniser.addNewOpponentName(opponentData.DriverRawName);
     }
     opponentData.Position = (int)participantStruct.mRacePosition;
     opponentData.UnFilteredPosition = opponentData.Position;
     opponentData.CompletedLaps = (int)participantStruct.mLapsCompleted;
     opponentData.CurrentSectorNumber = (int)participantStruct.mCurrentSector;
     opponentData.WorldPosition = new float[] { participantStruct.mWorldPosition[0], participantStruct.mWorldPosition[2] };
     opponentData.DistanceRoundTrack = participantStruct.mCurrentLapDistance;
     return opponentData;
 }
 public static pCarsAPIParticipantStruct getParticipantDataForName(pCarsAPIParticipantStruct[] pCarsAPIParticipantStructArray, String name, int index)
 {
     if (name != null && name.Length > 0)
     {
         foreach (pCarsAPIParticipantStruct data in pCarsAPIParticipantStructArray)
         {
             if (data.mName == name)
             {
                 return data;
             }
         }
     }
     return pCarsAPIParticipantStructArray[index];
 }
 public static Tuple<int, pCarsAPIParticipantStruct> getPlayerDataStruct(pCarsAPIParticipantStruct[] pCarsAPIParticipantStructArray, int viewedParticipantIndex)
 {
     if (!getPlayerByName)
     {
         return new Tuple<int, pCarsAPIParticipantStruct>(viewedParticipantIndex, pCarsAPIParticipantStructArray[viewedParticipantIndex]);
     }
     else if (playerSteamId == null)
     {
         if (userSpecifiedSteamId == null || userSpecifiedSteamId.Length == 0)
         {
             // get the player ID from the first viewed participant the app 'sees' and use this for the remainder of the app's run time
             pCarsAPIParticipantStruct likelyParticipantData = pCarsAPIParticipantStructArray[viewedParticipantIndex];
             playerSteamId = likelyParticipantData.mName;
             Console.WriteLine("Using player steam ID " + playerSteamId + " from the first reported viewed participant");
             if (playerSteamId == null || playerSteamId.Length == 0)
             {
                 getPlayerByName = false;
                 Console.WriteLine("Player steam ID is not valid, falling back to viewedParticipantIndex");
             }
             return new Tuple<int, pCarsAPIParticipantStruct>(viewedParticipantIndex, likelyParticipantData);
         }
         else
         {
             // use the steamID provided
             playerSteamId = userSpecifiedSteamId;
         }
     }
     for (int i=0; i<pCarsAPIParticipantStructArray.Length; i++)
     {
         if (pCarsAPIParticipantStructArray[i].mName == playerSteamId)
         {
             return new Tuple<int, pCarsAPIParticipantStruct> (i,pCarsAPIParticipantStructArray[i]);
         }
     }
     // no match in the block, so use the viewParticipantIndex
     getPlayerByName = false;
     return new Tuple<int, pCarsAPIParticipantStruct>(viewedParticipantIndex, pCarsAPIParticipantStructArray[viewedParticipantIndex]);
 }
예제 #5
0
        private Boolean opponentIsRacing(float currentOpponentX, float currentOpponentY, float previousOpponentX, float previousOpponentY,
            pCarsAPIParticipantStruct playerData, pCarsAPIParticipantStruct previousPlayerData, float interval)
        {
            float deltaX = Math.Abs(currentOpponentX - playerData.mWorldPosition[0]);
            float deltaY = Math.Abs(currentOpponentY - playerData.mWorldPosition[2]);
            if (deltaX > trackWidth || deltaY > trackWidth)
            {
                return false;
            }
            float opponentVelocityX = Math.Abs(currentOpponentX - previousOpponentX) / interval;
            float opponentVelocityY = Math.Abs(currentOpponentY - previousOpponentY) / interval;
            // hard code this - if the opponent car is going < 4m/s on both axis we're not interested
            if (opponentVelocityX < 4 && opponentVelocityY < 4)
            {
                return false;
            }

            float playerVelocityX = Math.Abs(playerData.mWorldPosition[0] - previousPlayerData.mWorldPosition[0]) / interval;
            float playerVelocityY = Math.Abs(playerData.mWorldPosition[2] - previousPlayerData.mWorldPosition[2]) / interval;

            if (Math.Abs(playerVelocityX - opponentVelocityX) > maxClosingSpeed || Math.Abs(playerVelocityY - opponentVelocityY) > maxClosingSpeed)
            {
               // Console.WriteLine("high closing speed: x = " + (playerVelocityX - opponentVelocityX) + " y = " + (playerVelocityY - opponentVelocityY));
                return false;
            }
            return true;
        }