コード例 #1
0
        private bool CheckInversion(RCT2TrackElementProperty property)
        {
            //Check for ride inversions
            if ((property.InputTrackBank != RCT2TrackElementProperty.RCT2TrackBank.Flipped && property.OutputTrackBank == RCT2TrackElementProperty.RCT2TrackBank.Flipped) ||
                (property.InputTrackBank == RCT2TrackElementProperty.RCT2TrackBank.Flipped && property.OutputTrackBank != RCT2TrackElementProperty.RCT2TrackBank.Flipped))
            {
                return(true);
            }

            return(false);
        }
コード例 #2
0
        public Vector2 CalculateRequiredMapSpace()
        {
            Vector2 requiredMapSpace       = new Vector2(0.0f, 0.0f);
            Vector2 posDisplacementCounter = new Vector2(0.0f, 0.0f);

            int            currentDirectionOffset = 0;
            List <Vector3> usedCells             = new List <Vector3>();
            Vector3        prevWorldDisplacement = new Vector3(0.0f, 0.0f, 0.0f);

            for (int i = 0; i < TrackData.Count; i++)
            {
                RCT2TrackElements.RCT2TrackElement element  = TrackData[i].TrackElement;
                RCT2TrackElementProperty           property = RCT2TrackElements.TrackElementPropertyMap[element];

                Vector3 worldDisplacement = LocalDisplacementToWorld(property.Displacement, currentDirectionOffset);

                prevWorldDisplacement += worldDisplacement;
                usedCells.Add(prevWorldDisplacement);

                currentDirectionOffset = UpdateRotation(currentDirectionOffset, property.DirectionChange);
            }

            //Find max X and Y distance of cells in list
            List <float> xVals = new List <float>();
            List <float> yVals = new List <float>();

            usedCells.ForEach(v =>
            {
                xVals.Add(v.X);
                yVals.Add(v.Z);
            });
            xVals.Sort();
            yVals.Sort();

            requiredMapSpace.X = Math.Abs(xVals.Last() - xVals.First());
            requiredMapSpace.Y = Math.Abs(yVals.Last() - yVals.First());

            return(requiredMapSpace);
        }
コード例 #3
0
        public int CalculateRideLengthInMeters()
        {
            //Approximate
            int rideLength = 0;

            for (int i = 0; i < TrackData.Count; i++)
            {
                RCT2TrackElements.RCT2TrackElement element  = TrackData[i].TrackElement;
                RCT2TrackElementProperty           property = RCT2TrackElements.TrackElementPropertyMap[element];

                int curLength = 0;
                int counter   = 0;

                if (property.Displacement.X != 0)
                {
                    curLength += (int)Math.Abs(property.Displacement.X * HorizontalUnitsToMeters);
                    counter++;
                }

                if (property.Displacement.Y != 0)
                {
                    curLength += (int)Math.Abs(property.Displacement.Y * VerticalUnitsToMeters);
                    counter++;
                }

                if (property.Displacement.Z != 0)
                {
                    curLength += (int)Math.Abs(property.Displacement.Z * HorizontalUnitsToMeters);
                    counter++;
                }

                if (counter > 0)
                {
                    rideLength += (curLength / counter);
                }
            }

            return(rideLength);
        }
コード例 #4
0
        public InvalidityCode CheckValidity()
        {
            //Following Validity Checks:
            // - All Track Pieces connect to the one before it
            // - Track doesn't intersect with itself
            // - Track doesn't exceed max height
            // - Track doesn't go underground (Go lower than the station height)
            // - Track's velocity doesn't go negative
            // - Track has more than one OnRidePhoto
            bool hasRidePhoto = false;

            if (TrackData.Count <= 0)
            {
                return(InvalidityCode.NoTrack);
            }

            //Negative Velocity
            if (!velocityChecked)
            {
                PopulateRideStatistics();
            }

            if (velocityGoesNegative)
            {
                return(InvalidityCode.NegativeVelocity);
            }

            float currentYDisplacement = 0;
            RCT2TrackElementProperty prevElementProperty = RCT2TrackElements.TrackElementPropertyMap[TrackData[0].TrackElement];
            List <Vector3>           UsedCells           = new List <Vector3>();
            Vector3 prevWorldPos         = new Vector3(0.0f, 0.0f, 0.0f);
            int     worldDirectionChange = 0;

            for (int i = 0; i < TrackData.Count; i++)
            {
                RCT2TrackElements.RCT2TrackElement currentElement = TrackData[i].TrackElement;
                RCT2TrackElementProperty           property       = RCT2TrackElements.TrackElementPropertyMap[currentElement];

                // OnRidePhoto Checks
                if (currentElement == RCT2TrackElements.RCT2TrackElement.OnRidePhoto)
                {
                    if (hasRidePhoto)
                    {
                        return(InvalidityCode.TwoRidePhotos);
                    }
                    else
                    {
                        hasRidePhoto = true;
                    }
                }

                // Height Checks
                currentYDisplacement += property.Displacement.Y;
                if (currentYDisplacement >= MaxUnitsOfDisplacement)
                {
                    return(InvalidityCode.ExceedMaxHeight);
                }
                if (currentYDisplacement < 0)
                {
                    return(InvalidityCode.ExceedMinHeight);
                }

                //Prev Element Matching Test
                if (i > 0 &&
                    (prevElementProperty.OutputTrackBank != property.InputTrackBank ||
                     prevElementProperty.OutputTrackDegree != property.InputTrackDegree))
                {
                    return(InvalidityCode.DoesntConnectToPrior);
                }

                //Intersection Tests
                //Get the world version of our property displacement
                //ie, if the segment moves 1 forward, but is already rotated to the left
                //    by 90°, then it actually moves right by 1
                Vector3 worldDisplacement = LocalDisplacementToWorld(property.Displacement, worldDirectionChange);
                Vector3 testCell          = prevWorldPos;
                //Check every tile used in this segment
                //Code is so gross Im so sorry
                for (int x = 1; x <= Math.Abs(worldDisplacement.X); x++)
                {
                    testCell = prevWorldPos + new Vector3(Math.Sign(worldDisplacement.X) * (x), 0, 0);
                    if (!UsedCells.Contains(testCell))
                    {
                        UsedCells.Add(testCell);
                    }
                    else
                    {
                        return(InvalidityCode.Intersection);
                    }
                }
                prevWorldPos = testCell;
                for (int y = 1; y <= Math.Abs(worldDisplacement.Y); y++)
                {
                    testCell = prevWorldPos + new Vector3(0, Math.Sign(worldDisplacement.Y) * (y), 0);
                    if (!UsedCells.Contains(testCell))
                    {
                        UsedCells.Add(testCell);
                    }
                    else
                    {
                        return(InvalidityCode.Intersection);
                    }
                }
                prevWorldPos = testCell;
                for (int z = 1; z <= Math.Abs(worldDisplacement.Z); z++)
                {
                    testCell = prevWorldPos + new Vector3(0, 0, Math.Sign(worldDisplacement.Z) * (z));
                    if (!UsedCells.Contains(testCell))
                    {
                        UsedCells.Add(testCell);
                    }
                    else
                    {
                        return(InvalidityCode.Intersection);
                    }
                }
                prevWorldPos = testCell;

                //Update World Direction Changes
                worldDirectionChange = UpdateRotation(worldDirectionChange, property.DirectionChange);

                //Update variables
                prevElementProperty = property;
            }

            return(InvalidityCode.Valid);
        }
コード例 #5
0
        private float CalcVelocity(float currentVelocity, RCT2TrackElements.RCT2TrackElement element, RCT2Qualifier qualifier, RCT2TrackElementProperty property)
        {
            //Check if it's a Chain lift or a station
            if (qualifier.IsChainLift)
            {
                return(Math.Max(currentVelocity, ChainLiftSpeed));
            }
            else if (element == RCT2TrackElements.RCT2TrackElement.BeginStation ||
                     element == RCT2TrackElements.RCT2TrackElement.MiddleStation ||
                     element == RCT2TrackElements.RCT2TrackElement.EndStation)
            {
                return(Math.Max(currentVelocity, StationSpeed));
            }

            float acceleration = 0;

            //Try to get current acceleration from the map
            try
            {
                acceleration = RCT2TrackElementProperty.TrackAccelerationMap[(int)-property.Displacement.Y];
            }
            catch
            {
                Console.WriteLine($"Unable to find acceleration value for track piece {element.ToString()}");
            }

            float newVelocity = currentVelocity + acceleration;

            if (newVelocity <= 0)
            {
                velocityGoesNegative = true;
            }

            return(newVelocity);
        }
コード例 #6
0
        public void PopulateRideStatistics()
        {
            //Inversion Data
            int tempInvCount = 0;

            //Velocity Data
            float totalVelocity   = 0;
            float vehicleVelocity = 0;
            float tempMaxSpeed    = 0;

            //Drop Data
            int   dropCount            = 0;
            bool  inDrop               = false;
            float tempHighestDrop      = 0;
            float curDropHeight        = 0;
            int   tempAirTimeInSeconds = 0;

            //G Forces
            float maxLatG = 0;
            float maxPosG = 0;
            float maxNegG = 0;

            float previousLatG  = 0;
            float previousVertG = 0;

            for (int i = 0; i < TrackData.Count - 1; i++)
            {
                RCT2TrackElementProperty           property = RCT2TrackElements.TrackElementPropertyMap[TrackData[i].TrackElement];
                RCT2TrackElements.RCT2TrackElement element  = TrackData[i].TrackElement;

                //----Check for ride inversions----
                if (CheckInversion(property))
                {
                    tempInvCount++;
                }

                //----Velocity Calculations----
                float tempVel = CalcVelocity(vehicleVelocity, element, TrackData[i].Qualifier, property);
                vehicleVelocity = tempVel;
                totalVelocity  += tempVel;

                if (tempVel > tempMaxSpeed)
                {
                    tempMaxSpeed = tempVel;
                }

                //----Drop Calculations----
                //We've entered a drop
                if (property.Displacement.Y < 0 && !inDrop)
                {
                    //Increment our counters
                    inDrop = true;
                    dropCount++;
                    curDropHeight += property.Displacement.Y * VerticalUnitsToMeters;
                }
                //If we're still in a drop
                else if (property.Displacement.Y < 0)
                {
                    //Add to our measurement of this drop
                    curDropHeight += property.Displacement.Y * VerticalUnitsToMeters;
                }
                //If we end the drop
                else if (property.Displacement.Y >= 0 && inDrop)
                {
                    //Reset our values
                    inDrop = false;
                    if (Math.Abs(curDropHeight) > tempHighestDrop)
                    {
                        tempHighestDrop = Math.Abs(curDropHeight);
                    }
                    curDropHeight = 0;
                }

                //----G Forces----
                float latG  = 0;
                float vertG = 0;
                TrackData[i].GetGForces(vehicleVelocity, out latG, out vertG);

                //Calc air time
                if (vertG < 0)
                {
                    //TODO: Translate into seconds, not sure how to do that really!
                    tempAirTimeInSeconds++;
                }

                //Get current G forces by averaging with previous ones
                vertG        += previousVertG;
                vertG        /= 2;
                previousVertG = vertG;

                latG        += previousLatG;
                latG        /= 2;
                previousLatG = latG;

                latG = Math.Abs(latG);

                //See if it's more than our current maX
                if (latG > maxLatG)
                {
                    maxLatG = latG;
                }
                //Vertical Gs
                if (vertG < 0)
                {
                    //Keep track of Max
                    if (Math.Abs(vertG) > maxNegG)
                    {
                        maxNegG = Math.Abs(vertG);
                    }
                }
                else
                {
                    //Keep track of Max
                    if (vertG > maxPosG)
                    {
                        maxPosG = vertG;
                    }
                }
            }

            //Apply the new values to our global vars
            NumOfInversions = tempInvCount;

            NumOfDrops  = dropCount;
            HighestDrop = (int)tempHighestDrop;

            AverageSpeed    = (int)(totalVelocity / TrackData.Count);
            MaxSpeed        = (int)tempMaxSpeed;
            velocityChecked = true;

            MaxLateralG  = maxLatG;
            MaxPositiveG = maxPosG;
            MaxNegativeG = maxNegG;

            AirTimeInSeconds = tempAirTimeInSeconds;

            float localExcitement = CalculateExcitement();
            float localIntensity  = CalculateIntensity();
            float localNausea     = CalculateNausea();

            ApplyPenalties(ref localExcitement, ref localIntensity, ref localNausea);

            Excitement = localExcitement;
            Intensity  = localIntensity;
            Nausea     = localNausea;
        }