Exemple #1
0
        public static pCars2APIStruct MergeWithExistingState(pCars2APIStruct existingState, sParticipantsData participantsData)
        {
            if (existingState.mParticipantData == null)
            {
                existingState.mParticipantData = new pCars2APIParticipantStruct[32];
            }
            int offset = (participantsData.mPartialPacketIndex - 1) * 16;

            // existingState is a struct, so any changes we make as we iterate this array will be done to a copy, not a reference
            for (int i = offset; i < offset + 16 && i < existingState.mParticipantData.Length; i++)
            {
                pCars2APIParticipantStruct existingParticipant = existingState.mParticipantData[i];
                existingParticipant.mName         = participantsData.sName[i - offset].nameByteArray;
                existingState.mParticipantData[i] = existingParticipant;
            }
            return(existingState);
        }
Exemple #2
0
        // For double-file manual rolling starts. Will only work when the cars are all nicely settled on the grid - preferably
        // when the game thinks the race has just started
        public override Tuple <GridSide, Dictionary <int, GridSide> > getGridSide(Object currentStateObj)
        {
            CrewChiefV4.PCars2.PCars2SharedMemoryReader.PCars2StructWrapper currentWrapper = (CrewChiefV4.PCars2.PCars2SharedMemoryReader.PCars2StructWrapper)currentStateObj;
            pCars2APIStruct            latestRawData  = currentWrapper.data;
            int                        playerIndex    = PCars2GameStateMapper.getPlayerIndex(latestRawData);
            pCars2APIParticipantStruct playerData     = latestRawData.mParticipantData[playerIndex];
            float                      playerRotation = latestRawData.mOrientation[1];

            if (playerRotation < 0)
            {
                playerRotation = (float)(2 * Math.PI) + playerRotation;
            }
            playerRotation = (float)(2 * Math.PI) - playerRotation;
            float playerXPosition        = playerData.mWorldPosition[0];
            float playerZPosition        = playerData.mWorldPosition[2];
            int   playerStartingPosition = (int)playerData.mRacePosition;
            int   numCars = latestRawData.mNumParticipants;

            return(getGridSideInternal(latestRawData, playerRotation, playerXPosition, playerZPosition, playerStartingPosition, numCars));
        }
Exemple #3
0
        public override void trigger(Object lastStateObj, Object currentStateObj, GameStateData currentGameState)
        {
            if (paused)
            {
                return;
            }
            CrewChiefV4.PCars2.PCars2SharedMemoryReader.PCars2StructWrapper currentWrapper = (CrewChiefV4.PCars2.PCars2SharedMemoryReader.PCars2StructWrapper)currentStateObj;
            pCars2APIStruct currentState = currentWrapper.data;
            ePitMode        pitMode      = (ePitMode)currentState.mPitMode;
            eGameState      gameState    = (eGameState)currentState.mGameState;

            // game state is 3 for paused, 5 for replay. No idea what 4 is...
            if (pitMode != ePitMode.PIT_MODE_NONE ||
                gameState == eGameState.GAME_FRONT_END ||
                (gameState == eGameState.GAME_INGAME_PAUSED && !CrewChief.Debugging) ||
                gameState == eGameState.GAME_INGAME_REPLAY || gameState == eGameState.GAME_FRONT_END_REPLAY ||
                gameState == eGameState.GAME_EXITED)
            {
                // don't ignore the paused game updates if we're in debug mode
                return;
            }
            CrewChiefV4.PCars2.PCars2SharedMemoryReader.PCars2StructWrapper previousWrapper = (CrewChiefV4.PCars2.PCars2SharedMemoryReader.PCars2StructWrapper)lastStateObj;
            pCars2APIStruct lastState = previousWrapper.data;

            DateTime now      = new DateTime(currentWrapper.ticksWhenRead);
            float    interval = (float)(((double)currentWrapper.ticksWhenRead - (double)previousWrapper.ticksWhenRead) / (double)TimeSpan.TicksPerSecond);

            if (currentState.mRaceState == (int)eRaceState.RACESTATE_RACING &&
                lastState.mRaceState != (int)eRaceState.RACESTATE_RACING)
            {
                timeToStartSpotting = now.Add(TimeSpan.FromSeconds(timeAfterRaceStartToActivate));
            }
            // this check looks a bit funky... whe we start a practice session, the raceState is not_started
            // until we cross the line for the first time. Which is retarded really.
            if (currentState.mRaceState == (int)eRaceState.RACESTATE_INVALID || now < timeToStartSpotting ||
                (currentState.mSessionState == (int)eSessionState.SESSION_RACE && currentState.mRaceState == (int)eRaceState.RACESTATE_NOT_STARTED))
            {
                return;
            }

            if (enabled && currentState.mNumParticipants > 1 &&
                (enableSpotterInTimetrial || currentState.mSessionState != (uint)eSessionState.SESSION_TIME_ATTACK))
            {
                int playerIndex = PCars2GameStateMapper.getPlayerIndex(currentState);
                if (playerIndex != currentState.mViewedParticipantIndex)
                {
                    return;
                }
                pCars2APIParticipantStruct playerData = currentState.mParticipantData[playerIndex];
                if (currentGameState != null && currentGameState.Now > nextCarClassCheckDue)
                {
                    var carClass = currentGameState.carClass;
                    if (carClass != null && !String.Equals(currentPlayerCarClassID, carClass.getClassIdentifier()))
                    {
                        // Retrieve and use user overridable spotter car length/width.
                        this.internalSpotter.setCarDimensions(GlobalBehaviourSettings.spotterVehicleLength, GlobalBehaviourSettings.spotterVehicleWidth);
                        this.currentPlayerCarClassID = carClass.getClassIdentifier();
                    }
                    nextCarClassCheckDue = currentGameState.Now.AddSeconds(5);
                }
                float[] currentPlayerPosition = new float[] { playerData.mWorldPosition[0], playerData.mWorldPosition[2] };

                List <float[]> currentOpponentPositions = new List <float[]>();
                float[]        playerVelocityData       = new float[3];
                playerVelocityData[0] = currentState.mSpeed;
                playerVelocityData[1] = currentState.mWorldVelocity[0];
                playerVelocityData[2] = currentState.mWorldVelocity[2];

                positionsFilledForThisTick.Clear();
                positionsFilledForThisTick.Add(playerData.mRacePosition);
                for (int i = 0; i < currentState.mParticipantData.Count(); i++)
                {
                    if (i == playerIndex)
                    {
                        continue;
                    }
                    pCars2APIParticipantStruct opponentData = currentState.mParticipantData[i];
                    if (opponentData.mIsActive && !positionsFilledForThisTick.Contains(opponentData.mRacePosition))
                    {
                        float[] currentPositions = new float[] { opponentData.mWorldPosition[0], opponentData.mWorldPosition[2] };
                        currentOpponentPositions.Add(currentPositions);
                        positionsFilledForThisTick.Add(opponentData.mRacePosition);
                    }
                }
                if (currentOpponentPositions.Count() > 0)
                {
                    float playerRotation = currentState.mOrientation[1];
                    if (playerRotation < 0)
                    {
                        playerRotation = playerRotation * -1;
                    }
                    else
                    {
                        playerRotation = twoPi - playerRotation;
                    }
                    internalSpotter.triggerInternal(playerRotation, currentPlayerPosition, playerVelocityData, currentOpponentPositions);
                }
            }
        }
Exemple #4
0
        public static pCars2APIStruct MergeWithExistingState(pCars2APIStruct existingState, sTimingsData timingsData)
        {
            existingState.mNumParticipants    = timingsData.sNumParticipants;
            existingState.mEventTimeRemaining = timingsData.sEventTimeRemaining;// time remaining, -1 for invalid time,  -1 - laps remaining in lap based races  --
            existingState.mSplitTimeAhead     = timingsData.sSplitTimeAhead;
            existingState.mSplitTimeBehind    = timingsData.sSplitTimeBehind;
            existingState.mSplitTime          = timingsData.sSplitTime; // what's this?
            if (existingState.mParticipantData == null)
            {
                existingState.mParticipantData = new pCars2APIParticipantStruct[32];
            }
            if (existingState.mRaceStates == null)
            {
                existingState.mRaceStates = new uint[32];
            }
            if (existingState.mLapsInvalidated == null)
            {
                existingState.mLapsInvalidated = new byte[32];
            }
            if (existingState.mPitModes == null)
            {
                existingState.mPitModes = new uint[32];
            }
            if (existingState.mCurrentSector1Times == null)
            {
                existingState.mCurrentSector1Times = new float[32];
            }
            if (existingState.mCurrentSector2Times == null)
            {
                existingState.mCurrentSector2Times = new float[32];
            }
            if (existingState.mCurrentSector3Times == null)
            {
                existingState.mCurrentSector3Times = new float[32];
            }
            for (int i = 0; i < existingState.mParticipantData.Length; i++)
            {
                sParticipantInfo newParticipantInfo = timingsData.sParticipants[i];
                Boolean          isHuman            = (newParticipantInfo.sCarIndex >> 7) == 1;
                uint             carIndex           = (uint)newParticipantInfo.sCarIndex & 127;

                Boolean isActive = (newParticipantInfo.sRacePosition >> 7) == 1;
                pCars2APIParticipantStruct existingPartInfo = existingState.mParticipantData[i];

                if (isActive)
                {
                    existingPartInfo.mIsActive = i < existingState.mNumParticipants;

                    existingPartInfo.mCurrentLap = newParticipantInfo.sCurrentLap;
                    // is this safe?:
                    existingPartInfo.mLapsCompleted      = existingPartInfo.mCurrentLap - 1;
                    existingPartInfo.mCurrentLapDistance = newParticipantInfo.sCurrentLapDistance;
                    existingPartInfo.mRacePosition       = (uint)newParticipantInfo.sRacePosition & 127;
                    existingPartInfo.mCurrentSector      = newParticipantInfo.sSector & 7;

                    // err... laps completed is missing?
                    // existingPartInfo.mLapsCompleted = (uint)newParticipantInfo.sLapsCompleted & 127;
                    byte lapInvalidated = (byte)(newParticipantInfo.sRaceState >> 7);
                    existingState.mRaceStates[i] = (uint)newParticipantInfo.sRaceState & 127;
                    if (i == existingState.mViewedParticipantIndex)
                    {
                        existingState.mRaceState = existingState.mRaceStates[i];
                    }
                    existingState.mLapsInvalidated[i]    = lapInvalidated;
                    existingState.mPitModes[i]           = (uint)newParticipantInfo.sPitModeSchedule & 28;
                    existingState.mPitSchedules[i]       = (uint)newParticipantInfo.sPitModeSchedule & 3;
                    existingState.mHighestFlagColours[i] = (uint)newParticipantInfo.sHighestFlag & 28;
                    existingState.mHighestFlagReasons[i] = (uint)newParticipantInfo.sHighestFlag & 3;
                    // no obvious slot in MMF for currentTime - do we need it if we have currentsectortime for S3?
                    if (existingPartInfo.mCurrentSector == 1)
                    {
                        existingState.mCurrentSector1Times[i] = newParticipantInfo.sCurrentSectorTime;
                    }
                    if (existingPartInfo.mCurrentSector == 2)
                    {
                        existingState.mCurrentSector2Times[i] = newParticipantInfo.sCurrentSectorTime;
                    }
                    if (existingPartInfo.mCurrentSector == 3)
                    {
                        existingState.mCurrentSector3Times[i] = newParticipantInfo.sCurrentSectorTime;
                    }

                    // and now the bit magic for the extra position precision...
                    float[] newWorldPositions = toFloatArray(newParticipantInfo.sWorldPosition, 1);
                    float   xAdjustment       = ((float)((uint)newParticipantInfo.sSector >> 6 & 3)) / 4f;
                    float   zAdjustment       = ((float)((uint)newParticipantInfo.sSector >> 4 & 3)) / 4f;

                    newWorldPositions[0]            = newWorldPositions[0] + xAdjustment;
                    newWorldPositions[2]            = newWorldPositions[2] + zAdjustment;
                    existingPartInfo.mWorldPosition = newWorldPositions;

                    if (i == existingState.mViewedParticipantIndex)
                    {
                        existingState.mLapInvalidated    = lapInvalidated == 1;
                        existingState.mHighestFlagColour = existingState.mHighestFlagColours[i];
                        existingState.mHighestFlagReason = existingState.mHighestFlagReasons[i];
                        existingState.mPitMode           = existingState.mPitModes[i];
                        existingState.mPitSchedule       = existingState.mPitSchedules[i];
                    }
                }
                else
                {
                    existingPartInfo.mWorldPosition = new float[] { 0, 0, 0 };
                    existingPartInfo.mIsActive      = false;
                }
                existingState.mParticipantData[i] = existingPartInfo;
            }
            return(existingState);
        }