Exemple #1
0
        public override void SetDragPositionTopDownView(double?x = null, double?y = null, double?z = null)
        {
            if (!x.HasValue || !z.HasValue)
            {
                return;
            }

            PositionAngle posAngle = _posAngle.GetBasePositionAngle();
            double        dist     = MoreMath.GetDistanceBetween(posAngle.X, posAngle.Z, x.Value, z.Value);
            double        angle    = MoreMath.AngleTo_AngleUnits(posAngle.X, posAngle.Z, x.Value, z.Value);

            if (Rotates)
            {
                angle -= posAngle.Angle;
            }

            if (!KeyboardUtilities.IsCtrlHeld())
            {
                _posAngle.SetOffsetDist(dist);
            }
            if (!KeyboardUtilities.IsShiftHeld())
            {
                _posAngle.SetOffsetAngle(angle);
            }

            MapTracker mapTracker = GetParentMapTracker();

            mapTracker.SetSize((float)_posAngle.GetOffsetDist());
            mapTracker.SetLineWidth((float)_posAngle.GetOffsetAngle());
        }
        public override void SetDragPositionTopDownView(double?x = null, double?y = null, double?z = null)
        {
            if (!x.HasValue || !z.HasValue)
            {
                return;
            }

            PositionAngle posAngle = GetPositionAngle();
            double        dist     = MoreMath.GetDistanceBetween(posAngle.X, posAngle.Z, x.Value, z.Value);
            double        angle    = MoreMath.AngleTo_AngleUnits(posAngle.X, posAngle.Z, x.Value, z.Value);

            if (!KeyboardUtilities.IsCtrlHeld())
            {
                if (_useRecommendedArrowLength)
                {
                    SetRecommendedSize(dist);
                }
                else
                {
                    GetParentMapTracker().SetSize((float)(Scales ? dist : dist *Config.CurrentMapGraphics.MapViewScaleValue));
                }
            }
            if (!KeyboardUtilities.IsShiftHeld())
            {
                SetYaw(angle);
            }
        }
        protected override double GetYaw()
        {
            float x = Config.Stream.GetFloat(_posAngle.GetObjAddress() + ObjectConfig.XSpeedOffset);
            float z = Config.Stream.GetFloat(_posAngle.GetObjAddress() + ObjectConfig.ZSpeedOffset);

            return(MoreMath.AngleTo_AngleUnits(x, z));
        }
Exemple #4
0
        protected override double GetYaw()
        {
            float x = Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.XSpeedOffset);
            float z = Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.ZSpeedOffset);

            return(MoreMath.AngleTo_AngleUnits(x, z));
        }
        public override void SetDragPositionTopDownView(double?x = null, double?y = null, double?z = null)
        {
            if (!x.HasValue || !z.HasValue)
            {
                return;
            }

            PositionAngle posAngle = GetPositionAngle();
            double        dist     = MoreMath.GetDistanceBetween(posAngle.X, posAngle.Z, x.Value, z.Value);
            double        angle    = MoreMath.AngleTo_AngleUnits(posAngle.X, posAngle.Z, x.Value, z.Value);
            double        xDiff    = x.Value - posAngle.X;
            double        zDiff    = z.Value - posAngle.Z;

            if (_useRecommendedArrowLength)
            {
                Config.Stream.SetValue((float)xDiff, _posAngle.GetObjAddress() + ObjectConfig.XSpeedOffset);
                Config.Stream.SetValue((float)zDiff, _posAngle.GetObjAddress() + ObjectConfig.ZSpeedOffset);
            }
            else
            {
                GetParentMapTracker().SetSize((float)(Scales ? dist : dist *Config.CurrentMapGraphics.MapViewScaleValue));
                SetYaw(angle);
            }
        }
Exemple #6
0
        public override void SetDragPositionTopDownView(double?x = null, double?y = null, double?z = null)
        {
            if (!x.HasValue || !z.HasValue)
            {
                return;
            }

            PositionAngle posAngle = GetPositionAngle();
            double        dist     = MoreMath.GetDistanceBetween(posAngle.X, posAngle.Z, x.Value, z.Value);
            double        angle    = MoreMath.AngleTo_AngleUnits(posAngle.X, posAngle.Z, x.Value, z.Value);
            double        xDiff    = x.Value - posAngle.X;
            double        zDiff    = z.Value - posAngle.Z;

            if (_useRecommendedArrowLength)
            {
                Config.Stream.SetValue((float)xDiff, MarioConfig.StructAddress + MarioConfig.SlidingSpeedXOffset);
                Config.Stream.SetValue((float)zDiff, MarioConfig.StructAddress + MarioConfig.SlidingSpeedZOffset);
            }
            else
            {
                GetParentMapTracker().SetSize((float)(Scales ? dist : dist *Config.CurrentMapGraphics.MapViewScaleValue));
                WatchVariableSpecialUtilities.SetMarioSlidingAngle(angle);
            }
        }
Exemple #7
0
        public void UpdateFromMarioTab()
        {
            // Get Mario position and rotation
            float  x           = Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.XOffset);
            float  y           = Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.YOffset);
            float  z           = Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.ZOffset);
            ushort marioFacing = Config.Stream.GetUInt16(MarioConfig.StructAddress + MarioConfig.FacingYawOffset);
            float  rot         = (float)MoreMath.AngleUnitsToDegrees(marioFacing);

            // Update Mario map object
            MarioMapObject.X        = x;
            MarioMapObject.Y        = y;
            MarioMapObject.Z        = z;
            MarioMapObject.Rotation = rot;
            MarioMapObject.Show     = true;

            // Get holp position
            float holpX = Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.HolpXOffset);
            float holpY = Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.HolpYOffset);
            float holpZ = Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.HolpZOffset);

            // Update holp map object position
            HolpMapObject.X    = holpX;
            HolpMapObject.Y    = holpY;
            HolpMapObject.Z    = holpZ;
            HolpMapObject.Show = true;

            // Update camera position and rotation
            float  cameraX   = Config.Stream.GetSingle(CameraConfig.StructAddress + CameraConfig.XOffset);
            float  cameraY   = Config.Stream.GetSingle(CameraConfig.StructAddress + CameraConfig.YOffset);
            float  cameraZ   = Config.Stream.GetSingle(CameraConfig.StructAddress + CameraConfig.ZOffset);
            ushort cameraYaw = Config.Stream.GetUInt16(CameraConfig.StructAddress + CameraConfig.FacingYawOffset);
            float  cameraRot = (float)MoreMath.AngleUnitsToDegrees(cameraYaw);

            // Update floor triangle
            UInt32 floorTriangle = Config.Stream.GetUInt32(MarioConfig.StructAddress + MarioConfig.FloorTriangleOffset);

            if (floorTriangle != 0x00)
            {
                Int16 x1 = Config.Stream.GetInt16(floorTriangle + TriangleOffsetsConfig.X1);
                Int16 y1 = Config.Stream.GetInt16(floorTriangle + TriangleOffsetsConfig.Y1);
                Int16 z1 = Config.Stream.GetInt16(floorTriangle + TriangleOffsetsConfig.Z1);
                Int16 x2 = Config.Stream.GetInt16(floorTriangle + TriangleOffsetsConfig.X2);
                Int16 y2 = Config.Stream.GetInt16(floorTriangle + TriangleOffsetsConfig.Y2);
                Int16 z2 = Config.Stream.GetInt16(floorTriangle + TriangleOffsetsConfig.Z2);
                Int16 x3 = Config.Stream.GetInt16(floorTriangle + TriangleOffsetsConfig.X3);
                Int16 y3 = Config.Stream.GetInt16(floorTriangle + TriangleOffsetsConfig.Y3);
                Int16 z3 = Config.Stream.GetInt16(floorTriangle + TriangleOffsetsConfig.Z3);
                FloorTriangleMapObject.X1 = x1;
                FloorTriangleMapObject.Z1 = z1;
                FloorTriangleMapObject.X2 = x2;
                FloorTriangleMapObject.Z2 = z2;
                FloorTriangleMapObject.X3 = x3;
                FloorTriangleMapObject.Z3 = z3;
                FloorTriangleMapObject.Y  = (y1 + y2 + y3) / 3;
            }
            FloorTriangleMapObject.Show = (floorTriangle != 0x00);

            // Update ceiling triangle
            UInt32 ceilingTriangle = Config.Stream.GetUInt32(MarioConfig.StructAddress + MarioConfig.CeilingTriangleOffset);

            if (ceilingTriangle != 0x00)
            {
                Int16 x1 = Config.Stream.GetInt16(ceilingTriangle + TriangleOffsetsConfig.X1);
                Int16 y1 = Config.Stream.GetInt16(ceilingTriangle + TriangleOffsetsConfig.Y1);
                Int16 z1 = Config.Stream.GetInt16(ceilingTriangle + TriangleOffsetsConfig.Z1);
                Int16 x2 = Config.Stream.GetInt16(ceilingTriangle + TriangleOffsetsConfig.X2);
                Int16 y2 = Config.Stream.GetInt16(ceilingTriangle + TriangleOffsetsConfig.Y2);
                Int16 z2 = Config.Stream.GetInt16(ceilingTriangle + TriangleOffsetsConfig.Z2);
                Int16 x3 = Config.Stream.GetInt16(ceilingTriangle + TriangleOffsetsConfig.X3);
                Int16 y3 = Config.Stream.GetInt16(ceilingTriangle + TriangleOffsetsConfig.Y3);
                Int16 z3 = Config.Stream.GetInt16(ceilingTriangle + TriangleOffsetsConfig.Z3);
                CeilingTriangleMapObject.X1 = x1;
                CeilingTriangleMapObject.Z1 = z1;
                CeilingTriangleMapObject.X2 = x2;
                CeilingTriangleMapObject.Z2 = z2;
                CeilingTriangleMapObject.X3 = x3;
                CeilingTriangleMapObject.Z3 = z3;
                CeilingTriangleMapObject.Y  = (y1 + y2 + y3) / 3;
            }
            CeilingTriangleMapObject.Show = (ceilingTriangle != 0x00);

            //List<TriangleDataModel> cogFloorTris = TriangleUtilities.GetObjectTrianglesForObject(0x80341E28)
            List <TriangleDataModel> cogFloorTris = TriangleUtilities.GetTrianglesInRange(0x8016DE30, 20)
                                                    .FindAll(tri => tri.Classification == TriangleClassification.Floor);

            for (int i = 0; i < _cogFloorTris.Count; i++)
            {
                if (i < cogFloorTris.Count)
                {
                    _cogFloorTris[i].Update(cogFloorTris[i]);
                    _cogFloorTris[i].Show = true;
                }
                else
                {
                    _cogFloorTris[i].Show = false;
                }
            }

            //List<TriangleDataModel> cog2FloorTris = TriangleUtilities.GetObjectTrianglesForObject(0x80342088)
            List <TriangleDataModel> cog2FloorTris = TriangleUtilities.GetTrianglesInRange(0x8016E1F0, 20)
                                                     .FindAll(tri => tri.Classification == TriangleClassification.Floor);

            for (int i = 0; i < _cog2FloorTris.Count; i++)
            {
                if (i < cog2FloorTris.Count)
                {
                    _cog2FloorTris[i].Update(cog2FloorTris[i]);
                    _cog2FloorTris[i].Show = true;
                }
                else
                {
                    _cog2FloorTris[i].Show = false;
                }
            }

            List <TriangleShape> cogWallTris = TriangleUtilities.GetWallTriangleHitboxComponents(
                TriangleUtilities.GetObjectTrianglesForObject(0x80341E28)
                .FindAll(tri => tri.Classification == TriangleClassification.Wall));

            for (int i = 0; i < _cogWallTris.Count; i++)
            {
                if (i < cogWallTris.Count)
                {
                    _cogWallTris[i].Update(cogWallTris[i]);
                    _cogWallTris[i].Show = true;
                }
                else
                {
                    _cogWallTris[i].Show = false;
                }
            }

            for (int numSides = SHAPE_MIN_SIDES; numSides <= SHAPE_MAX_SIDSE; numSides++)
            {
                (List <TriangleShape> floors, List <TriangleShape> walls) = GetTriShapes(numSides);
                int index = numSides - SHAPE_MIN_SIDES;
                List <TriangleMap2Object> floorTris = _triObjectFloors[index];
                List <TriangleMap2Object> wallTris  = _triObjectWalls[index];
                for (int i = 0; i < floorTris.Count; i++)
                {
                    floorTris[i].Update(floors[i]);
                    floorTris[i].Show = true;
                }
                for (int i = 0; i < wallTris.Count; i++)
                {
                    wallTris[i].Update(walls[i]);
                    wallTris[i].Show = true;
                }
            }

            // Update intended next position map object position
            float  normY               = floorTriangle == 0 ? 1 : Config.Stream.GetSingle(floorTriangle + TriangleOffsetsConfig.NormY);
            float  hSpeed              = Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.HSpeedOffset);
            float  floorY              = Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.FloorYOffset);
            bool   aboveFloor          = y > floorY + 0.001;
            double multiplier          = aboveFloor ? 1 : normY;
            double defactoSpeed        = hSpeed * multiplier;
            double defactoSpeedQStep   = defactoSpeed * 0.25;
            ushort marioAngle          = Config.Stream.GetUInt16(MarioConfig.StructAddress + MarioConfig.FacingYawOffset);
            ushort marioAngleTruncated = MoreMath.NormalizeAngleTruncated(marioAngle);

            (double xDist, double zDist) = MoreMath.GetComponentsFromVector(defactoSpeedQStep, marioAngleTruncated);
            double intendedNextPositionX = MoreMath.MaybeNegativeModulus(x + xDist, 65536);
            double intendedNextPositionZ = MoreMath.MaybeNegativeModulus(z + zDist, 65536);

            IntendedNextPositionMapObject.X = (float)intendedNextPositionX;
            IntendedNextPositionMapObject.Z = (float)intendedNextPositionZ;
            bool   marioStationary             = x == intendedNextPositionX && z == intendedNextPositionZ;
            double angleToIntendedNextPosition = MoreMath.AngleTo_AngleUnits(x, z, intendedNextPositionX, intendedNextPositionZ);

            IntendedNextPositionMapObject.Rotation =
                marioStationary ? (float)MoreMath.AngleUnitsToDegrees(marioAngle) : (float)MoreMath.AngleUnitsToDegrees(angleToIntendedNextPosition);
            IntendedNextPositionMapObject.Rotation = rot;

            // Update camera map object position
            CameraMapObject.X        = cameraX;
            CameraMapObject.Y        = cameraY;
            CameraMapObject.Z        = cameraZ;
            CameraMapObject.Rotation = cameraRot;
        }
        private List <List <(float x, float z, Color color)> > GetOrthographicDimensionsForControl()
        {
            List <List <(float x, float y, float z, Color color)> > vertexLists = Get3DDimensions().ConvertAll(dimension =>
            {
                if (_useCrossSection)
                {
                    double dist = MoreMath.GetDistanceBetween(
                        Config.CurrentMapGraphics.MapViewCenterXValue,
                        Config.CurrentMapGraphics.MapViewCenterZValue,
                        dimension.centerX,
                        dimension.centerZ);
                    double angle = MoreMath.AngleTo_AngleUnits(
                        Config.CurrentMapGraphics.MapViewCenterXValue,
                        Config.CurrentMapGraphics.MapViewCenterZValue,
                        dimension.centerX,
                        dimension.centerZ);
                    (double sidewaysDist, double forwardsDist) =
                        MoreMath.GetComponentsFromVectorRelatively(
                            dist, angle, Config.CurrentMapGraphics.MapViewYawValue);
                    if (forwardsDist > dimension.radius || forwardsDist < -1 * dimension.radius)
                    {
                        return(null);
                    }
                    (double pointX, double pointZ) = MoreMath.AddVectorToPoint(
                        -1 * forwardsDist,
                        Config.CurrentMapGraphics.MapViewYawValue,
                        dimension.centerX,
                        dimension.centerZ);
                    double legDist             = Math.Sqrt(dimension.radius * dimension.radius - forwardsDist * forwardsDist);
                    (float leftX, float leftZ) = ((float, float))MoreMath.AddVectorToPoint(
                        legDist, Config.CurrentMapGraphics.MapViewYawValue + 16384, pointX, pointZ);
                    (float rightX, float rightZ) = ((float, float))MoreMath.AddVectorToPoint(
                        legDist, Config.CurrentMapGraphics.MapViewYawValue - 16384, pointX, pointZ);
                    return(new List <(float x, float y, float z, Color color)>()
                    {
                        (leftX, dimension.minY, leftZ, dimension.color),
                        (rightX, dimension.minY, rightZ, dimension.color),
                        (rightX, dimension.maxY, rightZ, dimension.color),
                        (leftX, dimension.maxY, leftZ, dimension.color),
                    });
                }
                switch (Config.CurrentMapGraphics.MapViewYawValue)
                {
                case 0:
                case 32768:
                    return(new List <(float x, float y, float z, Color color)>()
                    {
                        (dimension.centerX - dimension.radius, dimension.minY, dimension.centerZ, dimension.color),
                        (dimension.centerX + dimension.radius, dimension.minY, dimension.centerZ, dimension.color),
                        (dimension.centerX + dimension.radius, dimension.maxY, dimension.centerZ, dimension.color),
                        (dimension.centerX - dimension.radius, dimension.maxY, dimension.centerZ, dimension.color),
                    });

                case 16384:
                case 49152:
                    return(new List <(float x, float y, float z, Color color)>()
                    {
                        (dimension.centerX, dimension.minY, dimension.centerZ - dimension.radius, dimension.color),
                        (dimension.centerX, dimension.minY, dimension.centerZ + dimension.radius, dimension.color),
                        (dimension.centerX, dimension.maxY, dimension.centerZ + dimension.radius, dimension.color),
                        (dimension.centerX, dimension.maxY, dimension.centerZ - dimension.radius, dimension.color),
                    });

                default:
                    double sideAngle = MoreMath.RotateAngleCW(Config.CurrentMapGraphics.MapViewYawValue, 16384);
                    (float sideDiffX, float sideDiffZ) = ((float, float))MoreMath.GetComponentsFromVector(dimension.radius, sideAngle);
                    return(new List <(float x, float y, float z, Color color)>()
                    {
                        (dimension.centerX - sideDiffX, dimension.minY, dimension.centerZ - sideDiffZ, dimension.color),
                        (dimension.centerX + sideDiffX, dimension.minY, dimension.centerZ + sideDiffZ, dimension.color),
                        (dimension.centerX + sideDiffX, dimension.maxY, dimension.centerZ + sideDiffZ, dimension.color),
                        (dimension.centerX - sideDiffX, dimension.maxY, dimension.centerZ - sideDiffZ, dimension.color),
                    });
                }
            }).FindAll(list => list != null);

            List <List <(float x, float z, Color color)> > vertexListsForControl =
                vertexLists.ConvertAll(vertexList => vertexList.ConvertAll(
                                           vertex =>
            {
                (float x, float z) = MapUtilities.ConvertCoordsForControlOrthographicView(vertex.x, vertex.y, vertex.z, UseRelativeCoordinates);
                return(x, z, vertex.color);
            }));

            return(vertexListsForControl);
        }
        public static void Test()
        {
            double        startX         = -2838;
            double        startY         = 1610.8349609375;
            double        startZ         = -42.8171844482422;
            List <double> initialHSpeeds = new List <double>()
            {
                -427922.90625, -641883.5, -962824.375, -1444235.625, -2166352.75, -3249528.25,
            };
            double goalX = 2806.789063;
            double goalY = 1033;
            double goalZ = -130.9819946;

            flatFloorTris = TriangleUtilities.GetLevelTriangles()
                            .FindAll(tri => tri.IsFloor() && tri.NormY == 1 && tri.SurfaceType != 0x0A);
            possibleAngles = Enumerable.Range(0, 4096).ToList().ConvertAll(i => 16 * i);

            List <double> moreHSpeeds = initialHSpeeds.ConvertAll(
                hSpeed => GetSuccessiveHSpeeds(hSpeed)).SelectMany(list => list).ToList();

            initialHSpeeds.AddRange(moreHSpeeds);
            initialHSpeeds = ControlUtilities.Randomize(initialHSpeeds);

            Queue <MarioPuState> queue = new Queue <MarioPuState>();

            initialHSpeeds.ForEach(hSpeed => queue.Enqueue(
                                       new MarioPuState(startX, startY, startZ, hSpeed, 0, null, 0)));

            Config.Print("START");
            int lastIndex = -1;

            while (queue.Count > 0)
            {
                MarioPuState dequeue = queue.Dequeue();
                if (dequeue.Index > lastIndex)
                {
                    lastIndex = dequeue.Index;
                    Config.Print("Now on index " + lastIndex);
                }

                List <int> anglesToUse;
                if (dequeue.Index < 2)
                {
                    anglesToUse = possibleAngles;
                }
                else
                {
                    int angle = MoreMath.NormalizeAngleTruncated(MoreMath.AngleTo_AngleUnits(goalX, goalZ, dequeue.X, dequeue.Z));
                    anglesToUse = new List <int>()
                    {
                        angle - 16, angle, angle + 16
                    };
                }

                foreach (int angle in anglesToUse)
                {
                    MarioPuState state = TestOverflowJump(dequeue, angle);
                    if (state == null)
                    {
                        continue;
                    }

                    double dist = MoreMath.GetDistanceBetween(state.X, state.Z, goalX, goalZ);
                    if (state.Index >= 2 && dist > Math.Abs(state.HSpeed))
                    {
                        continue;
                    }
                    if (dist < 1000 && state.Y == goalY)
                    {
                        Config.Print(dist);
                        Config.Print(state.GetLineage());
                    }

                    if (state.Index >= 3)
                    {
                        continue;
                    }
                    List <MarioPuState> nextStates = GetSuccessiveStates(state);
                    nextStates.Insert(0, state);
                    nextStates = ControlUtilities.Randomize(nextStates);
                    nextStates.ForEach(s => queue.Enqueue(s));
                }
            }
            Config.Print("END");
        }
Exemple #10
0
        private void ProcessSpecialVars()
        {
            var floorY = Config.Stream.GetSingle(Config.Mario.StructAddress + Config.Mario.FloorYOffset);

            // Get Mario position
            float marioX = Config.Stream.GetSingle(Config.Mario.StructAddress + Config.Mario.XOffset);
            float marioY = Config.Stream.GetSingle(Config.Mario.StructAddress + Config.Mario.YOffset);
            float marioZ = Config.Stream.GetSingle(Config.Mario.StructAddress + Config.Mario.ZOffset);

            marioX = PuUtilities.GetRelativePuPosition(marioX);
            marioY = PuUtilities.GetRelativePuPosition(marioY);
            marioZ = PuUtilities.GetRelativePuPosition(marioZ);

            float normX      = Config.Stream.GetSingle(TriangleAddress + Config.TriangleOffsets.NormX);
            float normY      = Config.Stream.GetSingle(TriangleAddress + Config.TriangleOffsets.NormY);
            float normZ      = Config.Stream.GetSingle(TriangleAddress + Config.TriangleOffsets.NormZ);
            float normOffset = Config.Stream.GetSingle(TriangleAddress + Config.TriangleOffsets.NormOffset);

            double uphillAngleRadians = Math.PI + Math.Atan2(normX, normZ);

            if (normX == 0 && normZ == 0)
            {
                uphillAngleRadians = double.NaN;
            }
            if (normY < -0.01)
            {
                uphillAngleRadians += Math.PI;
            }
            double downhillAngleRadians  = uphillAngleRadians + Math.PI;
            double lefthillAngleRadians  = uphillAngleRadians + Math.PI / 2;
            double righthillAngleRadians = uphillAngleRadians - Math.PI / 2;
            double uphillAngle           = MoreMath.RadiansToAngleUnits(uphillAngleRadians);
            double downhillAngle         = MoreMath.RadiansToAngleUnits(downhillAngleRadians);
            double lefthillAngle         = MoreMath.RadiansToAngleUnits(lefthillAngleRadians);
            double righthillAngle        = MoreMath.RadiansToAngleUnits(righthillAngleRadians);

            ushort marioAngle = Config.Stream.GetUInt16(Config.Mario.StructAddress + Config.Mario.YawFacingOffset);

            short v1X = Config.Stream.GetInt16(TriangleAddress + Config.TriangleOffsets.X1);
            short v1Y = Config.Stream.GetInt16(TriangleAddress + Config.TriangleOffsets.Y1);
            short v1Z = Config.Stream.GetInt16(TriangleAddress + Config.TriangleOffsets.Z1);
            short v2X = Config.Stream.GetInt16(TriangleAddress + Config.TriangleOffsets.X2);
            short v2Y = Config.Stream.GetInt16(TriangleAddress + Config.TriangleOffsets.Y2);
            short v2Z = Config.Stream.GetInt16(TriangleAddress + Config.TriangleOffsets.Z2);
            short v3X = Config.Stream.GetInt16(TriangleAddress + Config.TriangleOffsets.X3);
            short v3Y = Config.Stream.GetInt16(TriangleAddress + Config.TriangleOffsets.Y3);
            short v3Z = Config.Stream.GetInt16(TriangleAddress + Config.TriangleOffsets.Z3);

            var disToV = new double[]
            {
                Math.Pow(marioX - v1X, 2) + Math.Pow(marioY - v1Y, 2) + Math.Pow(marioZ - v1Z, 2),
                Math.Pow(marioX - v2X, 2) + Math.Pow(marioY - v2Y, 2) + Math.Pow(marioZ - v2Z, 2),
                Math.Pow(marioX - v3X, 2) + Math.Pow(marioY - v3Y, 2) + Math.Pow(marioZ - v3Z, 2)
            };

            _closestVertex = disToV.IndexOfMin() + 1;

            double angleMarioToV1 = MoreMath.AngleTo_AngleUnits(marioX, marioZ, v1X, v1Z);
            double angleV1ToMario = MoreMath.AngleTo_AngleUnits(v1X, v1Z, marioX, marioZ);
            double angleMarioToV2 = MoreMath.AngleTo_AngleUnits(marioX, marioZ, v2X, v2Z);
            double angleV2ToMario = MoreMath.AngleTo_AngleUnits(v2X, v2Z, marioX, marioZ);
            double angleMarioToV3 = MoreMath.AngleTo_AngleUnits(marioX, marioZ, v3X, v3Z);
            double angleV3ToMario = MoreMath.AngleTo_AngleUnits(v3X, v3Z, marioX, marioZ);

            foreach (IDataContainer specialVar in _specialWatchVars)
            {
                switch (specialVar.SpecialName)
                {
                case "DistanceAboveFloor":
                    (specialVar as DataContainer).Text = (marioY - floorY).ToString();
                    break;

                case "DistanceBelowCeiling":
                    (specialVar as DataContainer).Text = (Config.Stream.GetSingle(Config.Mario.StructAddress + Config.Mario.CeilingYOffset)
                                                          - marioY).ToString();
                    break;

                case "ClosestVertex":
                    (specialVar as DataContainer).Text = String.Format("V{0}", _closestVertex);
                    goto case "CheckTriangleExists";

                case "ClosestVertexX":
                    short coordX = 0;
                    switch (_closestVertex)
                    {
                    case 1:
                        coordX = v1X;
                        break;

                    case 2:
                        coordX = v2X;
                        break;

                    case 3:
                        coordX = v3X;
                        break;
                    }
                    (specialVar as DataContainer).Text = coordX.ToString();
                    goto case "CheckTriangleExists";

                case "ClosestVertexY":
                    short coordY = 0;
                    switch (_closestVertex)
                    {
                    case 1:
                        coordY = v1Y;
                        break;

                    case 2:
                        coordY = v2Y;
                        break;

                    case 3:
                        coordY = v3Y;
                        break;
                    }
                    (specialVar as DataContainer).Text = coordY.ToString();
                    goto case "CheckTriangleExists";

                case "ClosestVertexZ":
                    short coordZ = 0;
                    switch (_closestVertex)
                    {
                    case 1:
                        coordZ = v1Z;
                        break;

                    case 2:
                        coordZ = v2Z;
                        break;

                    case 3:
                        coordZ = v3Z;
                        break;
                    }
                    (specialVar as DataContainer).Text = coordZ.ToString();
                    goto case "CheckTriangleExists";

                case "UpHillAngle":
                    (specialVar as AngleDataContainer).AngleValue = uphillAngle;
                    goto case "CheckTriangleExistsAngle";

                case "DownHillAngle":
                    (specialVar as AngleDataContainer).AngleValue = downhillAngle;
                    goto case "CheckTriangleExistsAngle";

                case "LeftHillAngle":
                    (specialVar as AngleDataContainer).AngleValue = lefthillAngle;
                    goto case "CheckTriangleExistsAngle";

                case "RightHillAngle":
                    (specialVar as AngleDataContainer).AngleValue = righthillAngle;
                    goto case "CheckTriangleExistsAngle";

                case "UpHillDeltaAngle":
                    (specialVar as AngleDataContainer).AngleValue = marioAngle - uphillAngle;
                    goto case "CheckTriangleExistsAngle";

                case "DownHillDeltaAngle":
                    (specialVar as AngleDataContainer).AngleValue = marioAngle - downhillAngle;
                    goto case "CheckTriangleExistsAngle";

                case "LeftHillDeltaAngle":
                    (specialVar as AngleDataContainer).AngleValue = marioAngle - lefthillAngle;
                    goto case "CheckTriangleExistsAngle";

                case "RightHillDeltaAngle":
                    (specialVar as AngleDataContainer).AngleValue = marioAngle - righthillAngle;
                    goto case "CheckTriangleExistsAngle";

                case "Classification":
                    if (normY > 0.01)
                    {
                        (specialVar as DataContainer).Text = "Floor";
                    }
                    else if (normY < -0.01)
                    {
                        (specialVar as DataContainer).Text = "Ceiling";
                    }
                    else
                    {
                        (specialVar as DataContainer).Text = "Wall";
                    }
                    goto case "CheckTriangleExists";

                case "Steepness":
                    (specialVar as AngleDataContainer).AngleValue = MoreMath.RadiansToAngleUnits(Math.Acos(normY));
                    goto case "CheckTriangleExistsAngle";

                case "NormalDistAway":
                    (specialVar as DataContainer).Text = Math.Round(marioX * normX + marioY * normY + marioZ * normZ + normOffset, 3).ToString();
                    goto case "CheckTriangleExists";

                case "VerticalDistAway":
                    (specialVar as DataContainer).Text = Math.Round(marioY + (marioX * normX + marioZ * normZ + normOffset) / normY, 3).ToString();
                    goto case "CheckTriangleExists";

                case "HeightOnSlope":
                    (specialVar as DataContainer).Text = Math.Round((-marioX * normX - marioZ * normZ - normOffset) / normY, 3).ToString();
                    goto case "CheckTriangleExists";

                case "DistanceToV1":
                    (specialVar as DataContainer).Text = Math.Round(MoreMath.GetDistanceBetween(marioX, marioY, marioZ, v1X, v1Y, v1Z), 3).ToString();
                    goto case "CheckTriangleExists";

                case "YDistanceToV1":
                    (specialVar as DataContainer).Text = Math.Round(marioY - v1Y, 3).ToString();
                    goto case "CheckTriangleExists";

                case "XDistanceToV1":
                    (specialVar as DataContainer).Text = Math.Round(marioX - v1X, 3).ToString();
                    goto case "CheckTriangleExists";

                case "ZDistanceToV1":
                    (specialVar as DataContainer).Text = Math.Round(marioZ - v1Z, 3).ToString();
                    goto case "CheckTriangleExists";

                case "HDistanceToV1":
                    (specialVar as DataContainer).Text = Math.Round(MoreMath.GetDistanceBetween(marioX, marioZ, v1X, v1Z), 3).ToString();
                    goto case "CheckTriangleExists";

                case "DistanceToV2":
                    (specialVar as DataContainer).Text = Math.Round(MoreMath.GetDistanceBetween(marioX, marioY, marioZ, v2X, v2Y, v2Z), 3).ToString();
                    goto case "CheckTriangleExists";

                case "YDistanceToV2":
                    (specialVar as DataContainer).Text = Math.Round(marioY - v2Y, 3).ToString();
                    goto case "CheckTriangleExists";

                case "XDistanceToV2":
                    (specialVar as DataContainer).Text = Math.Round(marioX - v2X, 3).ToString();
                    goto case "CheckTriangleExists";

                case "ZDistanceToV2":
                    (specialVar as DataContainer).Text = Math.Round(marioZ - v2Z, 3).ToString();
                    goto case "CheckTriangleExists";

                case "HDistanceToV2":
                    (specialVar as DataContainer).Text = Math.Round(MoreMath.GetDistanceBetween(marioX, marioZ, v2X, v2Z), 3).ToString();
                    goto case "CheckTriangleExists";

                case "DistanceToV3":
                    (specialVar as DataContainer).Text = Math.Round(MoreMath.GetDistanceBetween(marioX, marioY, marioZ, v3X, v3Y, v3Z), 3).ToString();
                    goto case "CheckTriangleExists";

                case "YDistanceToV3":
                    (specialVar as DataContainer).Text = Math.Round(marioY - v3Y, 3).ToString();
                    goto case "CheckTriangleExists";

                case "XDistanceToV3":
                    (specialVar as DataContainer).Text = Math.Round(marioX - v3X, 3).ToString();
                    goto case "CheckTriangleExists";

                case "ZDistanceToV3":
                    (specialVar as DataContainer).Text = Math.Round(marioZ - v3Z, 3).ToString();
                    goto case "CheckTriangleExists";

                case "HDistanceToV3":
                    (specialVar as DataContainer).Text = Math.Round(MoreMath.GetDistanceBetween(marioX, marioZ, v3X, v3Z), 3).ToString();
                    goto case "CheckTriangleExists";

                case "DistanceToLine12":
                {
                    double signedDistToLine = MoreMath.GetSignedDistanceFromPointToLine(marioX, marioZ, v1X, v1Z, v2X, v2Z, v3X, v3Z, 1, 2);
                    (specialVar as DataContainer).Text = Math.Round(signedDistToLine, 3).ToString();
                }
                    goto case "CheckTriangleExists";

                case "DistanceToLine23":
                {
                    double signedDistToLine = MoreMath.GetSignedDistanceFromPointToLine(marioX, marioZ, v1X, v1Z, v2X, v2Z, v3X, v3Z, 2, 3);
                    (specialVar as DataContainer).Text = Math.Round(signedDistToLine, 3).ToString();
                }
                    goto case "CheckTriangleExists";

                case "DistanceToLine13":
                {
                    double signedDistToLine = MoreMath.GetSignedDistanceFromPointToLine(marioX, marioZ, v1X, v1Z, v2X, v2Z, v3X, v3Z, 3, 1);
                    (specialVar as DataContainer).Text = Math.Round(signedDistToLine, 3).ToString();
                }
                    goto case "CheckTriangleExists";

                case "AngleMarioToV1":
                    (specialVar as AngleDataContainer).AngleValue = angleMarioToV1;
                    goto case "CheckTriangleExistsAngle";

                case "DeltaAngleMarioToV1":
                    (specialVar as AngleDataContainer).AngleValue = marioAngle - angleMarioToV1;
                    goto case "CheckTriangleExistsAngle";

                case "AngleV1ToMario":
                    (specialVar as AngleDataContainer).AngleValue = angleV1ToMario;
                    goto case "CheckTriangleExistsAngle";

                case "AngleMarioToV2":
                    (specialVar as AngleDataContainer).AngleValue = angleMarioToV2;
                    goto case "CheckTriangleExistsAngle";

                case "DeltaAngleMarioToV2":
                    (specialVar as AngleDataContainer).AngleValue = marioAngle - angleMarioToV2;
                    goto case "CheckTriangleExistsAngle";

                case "AngleV2ToMario":
                    (specialVar as AngleDataContainer).AngleValue = angleV2ToMario;
                    goto case "CheckTriangleExistsAngle";

                case "AngleMarioToV3":
                    (specialVar as AngleDataContainer).AngleValue = angleMarioToV3;
                    goto case "CheckTriangleExistsAngle";

                case "DeltaAngleMarioToV3":
                    (specialVar as AngleDataContainer).AngleValue = marioAngle - angleMarioToV3;
                    goto case "CheckTriangleExistsAngle";

                case "AngleV3ToMario":
                    (specialVar as AngleDataContainer).AngleValue = angleV3ToMario;
                    goto case "CheckTriangleExistsAngle";

                case "AngleV1ToV2":
                    (specialVar as AngleDataContainer).AngleValue = MoreMath.AngleTo_AngleUnits(v1X, v1Z, v2X, v2Z);
                    goto case "CheckTriangleExistsAngle";

                case "AngleV2ToV1":
                    (specialVar as AngleDataContainer).AngleValue = MoreMath.AngleTo_AngleUnits(v2X, v2Z, v1X, v1Z);
                    goto case "CheckTriangleExistsAngle";

                case "AngleV2ToV3":
                    (specialVar as AngleDataContainer).AngleValue = MoreMath.AngleTo_AngleUnits(v2X, v2Z, v3X, v3Z);
                    goto case "CheckTriangleExistsAngle";

                case "AngleV3ToV2":
                    (specialVar as AngleDataContainer).AngleValue = MoreMath.AngleTo_AngleUnits(v3X, v3Z, v2X, v2Z);
                    goto case "CheckTriangleExistsAngle";

                case "AngleV1ToV3":
                    (specialVar as AngleDataContainer).AngleValue = MoreMath.AngleTo_AngleUnits(v1X, v1Z, v3X, v3Z);
                    goto case "CheckTriangleExistsAngle";

                case "AngleV3ToV1":
                    (specialVar as AngleDataContainer).AngleValue = MoreMath.AngleTo_AngleUnits(v3X, v3Z, v1X, v1Z);
                    goto case "CheckTriangleExistsAngle";

                case "ObjectTriCount":
                    (specialVar as DataContainer).Text =
                        (Config.Stream.GetInt32(Config.Triangle.TotalTriangleCountAddress) - Config.Stream.GetInt32(Config.Triangle.LevelTriangleCountAddress)).ToString();
                    break;

                case "ObjectNodeCount":
                    (specialVar as DataContainer).Text =
                        (Config.Stream.GetInt32(Config.Triangle.TotalNodeCountAddress) - Config.Stream.GetInt32(Config.Triangle.LevelNodeCountAddress)).ToString();
                    break;

                // Special
                case "CheckTriangleExists":
                    if (TriangleAddress == 0x0000)
                    {
                        (specialVar as DataContainer).Text = "(none)";
                        break;
                    }
                    break;

                case "CheckTriangleExistsAngle":
                    (specialVar as AngleDataContainer).ValueExists = (TriangleAddress != 0);
                    break;
                }
            }
        }