Example #1
0
        private void UpdateDisruptions(Vector2 pingSource, float worldPingRadius, float worldPrevPingRadius)
        {
            float worldPingRadiusSqr     = worldPingRadius * worldPingRadius;
            float worldPrevPingRadiusSqr = worldPrevPingRadius * worldPrevPingRadius;

            disruptedDirections.Clear();
            if (Level.Loaded == null)
            {
                return;
            }

            foreach (LevelObject levelObject in Level.Loaded.LevelObjectManager.GetAllObjects(pingSource, range * pingState))
            {
                if (levelObject.ActivePrefab?.SonarDisruption <= 0.0f)
                {
                    continue;
                }

                float   disruptionStrength = levelObject.ActivePrefab.SonarDisruption;
                Vector2 disruptionPos      = new Vector2(levelObject.Position.X, levelObject.Position.Y);

                float disruptionDist = Vector2.Distance(pingSource, disruptionPos);
                disruptedDirections.Add(new Pair <Vector2, float>((disruptionPos - pingSource) / disruptionDist, disruptionStrength));

                if (disruptionDist > worldPrevPingRadius && disruptionDist <= worldPingRadius)
                {
                    for (int i = 0; i < disruptionStrength * Level.GridCellSize * 0.02f; i++)
                    {
                        var blip = new SonarBlip(disruptionPos + Rand.Vector(Rand.Range(0.0f, Level.GridCellSize * 4 * disruptionStrength)), MathHelper.Lerp(1.0f, 1.5f, disruptionStrength), Rand.Range(1.0f, 2.0f + disruptionStrength));
                        sonarBlips.Add(blip);
                    }
                }
            }
        }
Example #2
0
        private bool CheckBlipVisibility(SonarBlip blip, Vector2 transducerPos)
        {
            Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;

            pos.Y = -pos.Y;

            float posDistSqr = pos.LengthSquared();

            if (posDistSqr > DisplayRadius * DisplayRadius)
            {
                blip.FadeTimer = 0.0f;
                return(false);
            }

            Vector2 dir = pos / (float)Math.Sqrt(posDistSqr);

            if (isLastPingDirectional)
            {
                if (Vector2.Dot(lastPingDirection, dir) < DirectionalPingDotProduct)
                {
                    blip.FadeTimer = 0.0f;
                    return(false);
                }
            }
            return(true);
        }
Example #3
0
        private void UpdateDisruptions(Vector2 pingSource, float worldPingRadius, float worldPrevPingRadius)
        {
            float worldPingRadiusSqr     = worldPingRadius * worldPingRadius;
            float worldPrevPingRadiusSqr = worldPrevPingRadius * worldPrevPingRadius;

            disruptedDirections.Clear();

            float searchRadius = Math.Min(range, worldPingRadius * 2);

            for (float x = pingSource.X - searchRadius; x < pingSource.X + searchRadius; x += Level.GridCellSize)
            {
                for (float y = pingSource.Y - searchRadius; y < pingSource.Y + searchRadius; y += Level.GridCellSize)
                {
                    Vector2 disruptionPos = new Vector2(
                        MathUtils.RoundTowardsClosest(x, Level.GridCellSize) + Level.GridCellSize / 2,
                        MathUtils.RoundTowardsClosest(y, Level.GridCellSize) + Level.GridCellSize / 2);

                    float disruptionStrength = Level.Loaded.GetSonarDisruptionStrength(disruptionPos);
                    if (disruptionStrength > 0.0f)
                    {
                        float disruptionDist = Vector2.Distance(pingSource, disruptionPos);
                        disruptedDirections.Add(new Pair <Vector2, float>((disruptionPos - pingSource) / disruptionDist, disruptionStrength));

                        if (disruptionDist > worldPrevPingRadius && disruptionDist <= worldPingRadius)
                        {
                            for (int i = 0; i < disruptionStrength * Level.GridCellSize * 0.02f; i++)
                            {
                                var blip = new SonarBlip(disruptionPos + Rand.Vector(Rand.Range(0.0f, Level.GridCellSize * 4 * disruptionStrength)), MathHelper.Lerp(1.0f, 1.5f, disruptionStrength), Rand.Range(1.0f, 2.0f + disruptionStrength));
                                sonarBlips.Add(blip);
                            }
                        }
                    }
                }
            }
        }
Example #4
0
        private void DrawBlip(SpriteBatch spriteBatch, SonarBlip blip, Vector2 transducerPos, Vector2 center, float strength)
        {
            strength = MathHelper.Clamp(strength, 0.0f, 1.0f);

            float distort = 1.0f - item.Condition / 100.0f;

            Vector2 pos = (blip.Position - transducerPos) * displayScale * zoom;

            pos.Y = -pos.Y;

            if (Rand.Range(0.5f, 2.0f) < distort)
            {
                pos.X = -pos.X;
            }
            if (Rand.Range(0.5f, 2.0f) < distort)
            {
                pos.Y = -pos.Y;
            }

            float posDistSqr = pos.LengthSquared();

            if (posDistSqr > DisplayRadius * DisplayRadius)
            {
                blip.FadeTimer = 0.0f;
                return;
            }

            if (sonarBlip == null)
            {
                GUI.DrawRectangle(spriteBatch, center + pos, Vector2.One * 4, Color.Magenta, true);
                return;
            }

            Vector2 dir    = pos / (float)Math.Sqrt(posDistSqr);
            Vector2 normal = new Vector2(dir.Y, -dir.X);
            float   scale  = (strength + 3.0f) * blip.Scale * zoomSqrt;
            Color   color  = ToolBox.GradientLerp(strength, blipColorGradient);

            sonarBlip.Draw(spriteBatch, center + pos, color, sonarBlip.Origin, blip.Rotation ?? MathUtils.VectorToAngle(pos),
                           blip.Size * scale * 0.04f, SpriteEffects.None, 0);

            pos += Rand.Range(0.0f, 1.0f) * dir + Rand.Range(-scale, scale) * normal;

            sonarBlip.Draw(spriteBatch, center + pos, color * 0.5f, sonarBlip.Origin, 0, scale * 0.08f, SpriteEffects.None, 0);
        }
Example #5
0
        private void CreateBlipsForLine(Vector2 point1, Vector2 point2, Vector2 transducerPos, float pingRadius, float prevPingRadius,
                                        float lineStep, float zStep, float range, float pingStrength, bool passive)
        {
            lineStep /= zoom;
            zStep    /= zoom;
            range    *= displayScale;
            float   length  = (point1 - point2).Length();
            Vector2 lineDir = (point2 - point1) / length;

            for (float x = 0; x < length; x += lineStep * Rand.Range(0.8f, 1.2f))
            {
                Vector2 point = point1 + lineDir * x;
                //point += cell.Translation;

                Vector2 pointDiff        = point - transducerPos;
                float   pointDist        = pointDiff.Length();
                float   displayPointDist = pointDist * displayScale;

                if (displayPointDist > DisplayRadius)
                {
                    continue;
                }
                if (displayPointDist < prevPingRadius || displayPointDist > pingRadius)
                {
                    continue;
                }

                bool disrupted = false;
                foreach (Pair <Vector2, float> disruptDir in disruptedDirections)
                {
                    float dot = Vector2.Dot(pointDiff / pointDist, disruptDir.First);
                    if (dot > 1.0f - disruptDir.Second)
                    {
                        disrupted = true;
                        break;
                    }
                }
                if (disrupted)
                {
                    continue;
                }

                float alpha = pingStrength * Rand.Range(1.5f, 2.0f);
                for (float z = 0; z < DisplayRadius - displayPointDist; z += zStep)
                {
                    Vector2 pos       = point + Rand.Vector(150.0f / zoom) + Vector2.Normalize(point - item.WorldPosition) * z / displayScale;
                    float   fadeTimer = alpha * (1.0f - displayPointDist / range);

                    int minDist = (int)(200 / zoom);
                    sonarBlips.RemoveAll(b => b.FadeTimer < fadeTimer && Math.Abs(pos.X - b.Position.X) < minDist && Math.Abs(pos.Y - b.Position.Y) < minDist);

                    var blip = new SonarBlip(pos, fadeTimer, 1.0f + ((displayPointDist + z) / DisplayRadius));
                    if (!passive && !CheckBlipVisibility(blip, transducerPos))
                    {
                        continue;
                    }

                    sonarBlips.Add(blip);
                    zStep += 0.5f / zoom;

                    if (z == 0)
                    {
                        alpha = Math.Min(alpha - 0.5f, 1.5f);
                    }
                    else
                    {
                        alpha -= 0.1f;
                    }

                    if (alpha < 0)
                    {
                        break;
                    }
                }
            }
        }
Example #6
0
        private void Ping(Vector2 pingSource, Vector2 transducerPos, float pingRadius, float prevPingRadius, float displayScale, float range, bool passive,
                          float pingStrength = 1.0f)
        {
            float prevPingRadiusSqr = prevPingRadius * prevPingRadius;
            float pingRadiusSqr     = pingRadius * pingRadius;

            //inside a hull -> only show the edges of the hull
            if (item.CurrentHull != null && DetectSubmarineWalls)
            {
                CreateBlipsForLine(
                    new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y),
                    new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y),
                    transducerPos,
                    pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive);

                CreateBlipsForLine(
                    new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
                    new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
                    transducerPos,
                    pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive);

                CreateBlipsForLine(
                    new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y),
                    new Vector2(item.CurrentHull.WorldRect.X, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
                    transducerPos,
                    pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive);

                CreateBlipsForLine(
                    new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y),
                    new Vector2(item.CurrentHull.WorldRect.Right, item.CurrentHull.WorldRect.Y - item.CurrentHull.Rect.Height),
                    transducerPos,
                    pingRadius, prevPingRadius, 50.0f, 5.0f, range, 2.0f, passive);

                return;
            }

            foreach (Submarine submarine in Submarine.Loaded)
            {
                if (submarine.HullVertices == null)
                {
                    continue;
                }
                if (!DetectSubmarineWalls)
                {
                    if (UseTransducers)
                    {
                        if (connectedTransducers.Any(t => submarine == t.Transducer.Item.Submarine ||
                                                     submarine.DockedTo.Contains(t.Transducer.Item.Submarine)))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if (item.Submarine == submarine)
                        {
                            continue;
                        }
                        if (item.Submarine != null && item.Submarine.DockedTo.Contains(submarine))
                        {
                            continue;
                        }
                    }
                }

                for (int i = 0; i < submarine.HullVertices.Count; i++)
                {
                    Vector2 start = ConvertUnits.ToDisplayUnits(submarine.HullVertices[i]);
                    Vector2 end   = ConvertUnits.ToDisplayUnits(submarine.HullVertices[(i + 1) % submarine.HullVertices.Count]);

                    if (item.Submarine == submarine)
                    {
                        start += Rand.Vector(500.0f);
                        end   += Rand.Vector(500.0f);
                    }

                    CreateBlipsForLine(
                        start + submarine.WorldPosition,
                        end + submarine.WorldPosition,
                        transducerPos,
                        pingRadius, prevPingRadius,
                        200.0f, 2.0f, range, 1.0f, passive);
                }
            }

            if (Level.Loaded != null && (item.CurrentHull == null || !DetectSubmarineWalls))
            {
                if (Level.Loaded.Size.Y - pingSource.Y < range)
                {
                    CreateBlipsForLine(
                        new Vector2(pingSource.X - range, Level.Loaded.Size.Y),
                        new Vector2(pingSource.X + range, Level.Loaded.Size.Y),
                        transducerPos,
                        pingRadius, prevPingRadius,
                        250.0f, 150.0f, range, pingStrength, passive);
                }

                List <Voronoi2.VoronoiCell> cells = Level.Loaded.GetCells(pingSource, 7);
                foreach (Voronoi2.VoronoiCell cell in cells)
                {
                    foreach (Voronoi2.GraphEdge edge in cell.Edges)
                    {
                        if (!edge.IsSolid)
                        {
                            continue;
                        }
                        float cellDot = Vector2.Dot(cell.Center - pingSource, (edge.Center + cell.Translation) - cell.Center);
                        if (cellDot > 0)
                        {
                            continue;
                        }

                        float facingDot = Vector2.Dot(
                            Vector2.Normalize(edge.Point1 - edge.Point2),
                            Vector2.Normalize(cell.Center - pingSource));

                        CreateBlipsForLine(
                            edge.Point1 + cell.Translation,
                            edge.Point2 + cell.Translation,
                            transducerPos,
                            pingRadius, prevPingRadius,
                            350.0f, 3.0f * (Math.Abs(facingDot) + 1.0f), range, pingStrength, passive);
                    }
                }

                foreach (RuinGeneration.Ruin ruin in Level.Loaded.Ruins)
                {
                    if (!MathUtils.CircleIntersectsRectangle(pingSource, range, ruin.Area))
                    {
                        continue;
                    }

                    foreach (var ruinShape in ruin.RuinShapes)
                    {
                        foreach (RuinGeneration.Line wall in ruinShape.Walls)
                        {
                            float cellDot = Vector2.Dot(
                                Vector2.Normalize(ruinShape.Center - pingSource),
                                Vector2.Normalize((wall.A + wall.B) / 2.0f - ruinShape.Center));
                            if (cellDot > 0)
                            {
                                continue;
                            }

                            CreateBlipsForLine(
                                wall.A, wall.B,
                                transducerPos,
                                pingRadius, prevPingRadius,
                                100.0f, 1000.0f, range, pingStrength, passive);
                        }
                    }
                }
            }

            foreach (Item item in Item.ItemList)
            {
                if (item.CurrentHull == null && item.Prefab.SonarSize > 0.0f)
                {
                    float pointDist = ((item.WorldPosition - pingSource) * displayScale).LengthSquared();

                    if (pointDist > prevPingRadiusSqr && pointDist < pingRadiusSqr)
                    {
                        var blip = new SonarBlip(
                            item.WorldPosition + Rand.Vector(item.Prefab.SonarSize),
                            MathHelper.Clamp(item.Prefab.SonarSize, 0.1f, pingStrength),
                            MathHelper.Clamp(item.Prefab.SonarSize * 0.1f, 0.1f, 10.0f));
                        if (!passive && !CheckBlipVisibility(blip, transducerPos))
                        {
                            continue;
                        }
                        sonarBlips.Add(blip);
                    }
                }
            }

            foreach (Character c in Character.CharacterList)
            {
                if (c.AnimController.CurrentHull != null || !c.Enabled)
                {
                    continue;
                }
                if (DetectSubmarineWalls && c.AnimController.CurrentHull == null && item.CurrentHull != null)
                {
                    continue;
                }

                foreach (Limb limb in c.AnimController.Limbs)
                {
                    float pointDist = ((limb.WorldPosition - pingSource) * displayScale).LengthSquared();

                    if (limb.SimPosition == Vector2.Zero || pointDist > DisplayRadius * DisplayRadius)
                    {
                        continue;
                    }

                    if (pointDist > prevPingRadiusSqr && pointDist < pingRadiusSqr)
                    {
                        var blip = new SonarBlip(
                            limb.WorldPosition + Rand.Vector(limb.Mass / 10.0f),
                            MathHelper.Clamp(limb.Mass, 0.1f, pingStrength),
                            MathHelper.Clamp(limb.Mass * 0.1f, 0.1f, 2.0f));
                        if (!passive && !CheckBlipVisibility(blip, transducerPos))
                        {
                            continue;
                        }
                        sonarBlips.Add(blip);
                    }
                }
            }
        }
Example #7
0
        public override void UpdateHUD(Character character, float deltaTime, Camera cam)
        {
            if (unsentChanges)
            {
                if (networkUpdateTimer <= 0.0f)
                {
#if CLIENT
                    if (GameMain.Client != null)
                    {
                        item.CreateClientEvent(this);
                        correctionTimer = CorrectionDelay;
                    }
#endif
                    if (GameMain.Server != null)
                    {
                        item.CreateServerEvent(this);
                    }

                    networkUpdateTimer = 0.1f;
                    unsentChanges      = false;
                }
            }
            networkUpdateTimer -= deltaTime;

            if (sonarView.Rect.Contains(PlayerInput.MousePosition))
            {
                float scrollSpeed = PlayerInput.ScrollWheelSpeed / 1000.0f;
                if (Math.Abs(scrollSpeed) > 0.0001f)
                {
                    zoomSlider.BarScroll += PlayerInput.ScrollWheelSpeed / 1000.0f;
                    zoomSlider.OnMoved(zoomSlider, zoomSlider.BarScroll);
                }
            }

            float distort = 1.0f - item.Condition / 100.0f;
            for (int i = sonarBlips.Count - 1; i >= 0; i--)
            {
                sonarBlips[i].FadeTimer -= deltaTime * MathHelper.Lerp(0.5f, 2.0f, distort);
                sonarBlips[i].Position  += sonarBlips[i].Velocity * deltaTime;

                if (sonarBlips[i].FadeTimer <= 0.0f)
                {
                    sonarBlips.RemoveAt(i);
                }
            }

            foreach (GUIComponent component in activeControlsContainer.Parent.GetAllChildren())
            {
                if (component is GUITextBlock textBlock)
                {
                    textBlock.TextColor = IsActive ? textBlock.Style.textColor : textBlock.Style.textColor * 0.5f;
                }
            }

            //sonar view can only get focus when the cursor is inside the circle
            sonarView.CanBeFocused =
                Vector2.DistanceSquared(sonarView.Rect.Center.ToVector2(), PlayerInput.MousePosition) <
                (sonarView.Rect.Width / 2 * sonarView.Rect.Width / 2);

            if (UseTransducers && connectedTransducers.Count == 0)
            {
                return;
            }

            Vector2 transducerCenter = UseTransducers ? GetTransducerCenter() : item.WorldPosition;
            transducerCenter += DisplayOffset;

            if (Level.Loaded != null)
            {
                Dictionary <LevelTrigger, Vector2> levelTriggerFlows = new Dictionary <LevelTrigger, Vector2>();
                foreach (LevelObject levelObject in Level.Loaded.LevelObjectManager.GetAllObjects(transducerCenter, range * pingState / zoom))
                {
                    //gather all nearby triggers that are causing the water to flow into the dictionary
                    foreach (LevelTrigger trigger in levelObject.Triggers)
                    {
                        Vector2 flow = trigger.GetWaterFlowVelocity();
                        //ignore ones that are barely doing anything (flow^2 < 1)
                        if (flow.LengthSquared() > 1.0f)
                        {
                            levelTriggerFlows.Add(trigger, flow);
                        }
                    }
                }

                foreach (KeyValuePair <LevelTrigger, Vector2> triggerFlow in levelTriggerFlows)
                {
                    LevelTrigger trigger = triggerFlow.Key;
                    Vector2      flow    = triggerFlow.Value;

                    float flowMagnitude = flow.Length();
                    if (Rand.Range(0.0f, 1.0f) < flowMagnitude / 1000.0f)
                    {
                        float   edgeDist = Rand.Range(0.0f, 1.0f);
                        Vector2 blipPos  = trigger.WorldPosition + Rand.Vector(trigger.ColliderRadius * edgeDist);
                        Vector2 blipVel  = flow;
                        if (trigger.ForceFalloff)
                        {
                            flow *= (1.0f - edgeDist);
                        }

                        //go through other triggers in range and add the flows of the ones that the blip is inside
                        foreach (KeyValuePair <LevelTrigger, Vector2> triggerFlow2 in levelTriggerFlows)
                        {
                            LevelTrigger trigger2 = triggerFlow2.Key;
                            if (trigger2 != trigger && Vector2.DistanceSquared(blipPos, trigger2.WorldPosition) < trigger2.ColliderRadius * trigger2.ColliderRadius)
                            {
                                Vector2 trigger2flow = triggerFlow2.Value;
                                if (trigger2.ForceFalloff)
                                {
                                    trigger2flow *= (1.0f - Vector2.Distance(blipPos, trigger2.WorldPosition) / trigger2.ColliderRadius);
                                }
                                blipVel += trigger2flow;
                            }
                        }
                        var flowBlip = new SonarBlip(blipPos, Rand.Range(0.5f, 1.0f), 1.0f)
                        {
                            Velocity = blipVel * Rand.Range(1.0f, 5.0f),
                            Size     = new Vector2(MathHelper.Lerp(0.4f, 5f, flowMagnitude / 500.0f), 0.2f),
                            Rotation = (float)Math.Atan2(-blipVel.Y, blipVel.X)
                        };
                        sonarBlips.Add(flowBlip);
                    }
                }
            }

            if (IsActive)
            {
                float pingRadius = DisplayRadius * pingState / zoom;
                UpdateDisruptions(transducerCenter, pingRadius / displayScale, prevPingRadius / displayScale);
                Ping(transducerCenter, transducerCenter,
                     pingRadius, prevPingRadius, displayScale, range / zoom, passive: false, pingStrength: 2.0f);
                prevPingRadius = pingRadius;
                return;
            }

            float passivePingRadius = (float)Math.Sin(Timing.TotalTime * 10);
            if (passivePingRadius > 0.0f)
            {
                disruptedDirections.Clear();
                foreach (AITarget t in AITarget.List)
                {
                    if (t.SoundRange <= 0.0f || !t.Enabled)
                    {
                        continue;
                    }

                    if (Vector2.DistanceSquared(t.WorldPosition, transducerCenter) < t.SoundRange * t.SoundRange)
                    {
                        Ping(t.WorldPosition, transducerCenter,
                             t.SoundRange * passivePingRadius * 0.2f, t.SoundRange * prevPassivePingRadius * 0.2f, displayScale, t.SoundRange,
                             passive: true, pingStrength: 0.5f);
                        sonarBlips.Add(new SonarBlip(t.WorldPosition, 1.0f, 1.0f));
                    }
                }
            }
            prevPassivePingRadius = passivePingRadius;
        }