]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Biome marker layer tweaks (#23663)
authormetalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Tue, 9 Jan 2024 11:44:38 +0000 (22:44 +1100)
committerGitHub <noreply@github.com>
Tue, 9 Jan 2024 11:44:38 +0000 (22:44 +1100)
* Biome marker layer tweaks

- Ensure veins get spawned at great perf cost (it's time-sliced anyway).
- Bump asteroids from 6 nodes to 10 nodes.

* Fixes

* magnet

* Magnet dictates wreck spawn

* Update Content.Shared/Procedural/PostGeneration/BiomeMarkerLayerPostGen.cs

* mraow

Content.Client/Salvage/UI/OfferingWindow.xaml
Content.Client/Salvage/UI/SalvageExpeditionConsoleBoundUserInterface.cs
Content.Client/Salvage/UI/SalvageMagnetBoundUserInterface.cs
Content.Server/Parallax/BiomeSystem.cs
Content.Server/Salvage/SalvageSystem.Magnet.cs
Resources/Locale/en-US/salvage/salvage-magnet.ftl

index 12f1f688c89d69b7143c75ba5d8b549948bd12d8..63b41aa652a574831069cb7edcd337acd71e6b21 100644 (file)
@@ -1,6 +1,5 @@
 <controls:FancyWindow xmlns="https://spacestation14.io"
                       xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
-                      Title="{Loc 'salvage-expedition-window-title'}"
                       MinSize="800 360">
     <BoxContainer Orientation="Vertical">
         <BoxContainer Orientation="Horizontal" Name="ProgressionBox" Visible="False">
index ac480614a4f0d6e065d766078d11e07bb159bb7c..8f1723d1f221165d27762bc0d9d7ade862a3c591 100644 (file)
@@ -31,6 +31,7 @@ public sealed class SalvageExpeditionConsoleBoundUserInterface : BoundUserInterf
     {
         base.Open();
         _window = new OfferingWindow();
+        _window.Title = Loc.GetString("salvage-expedition-window-title");
         _window.OnClose += Close;
         _window?.OpenCenteredLeft();
     }
index 0c1994c36fcb9d16b38e67823641fb81b1a5a88c..36fbdd90e2858c086377becd0e407e3b78a75be3 100644 (file)
@@ -21,6 +21,7 @@ public sealed class SalvageMagnetBoundUserInterface : BoundUserInterface
     {
         base.Open();
         _window = new OfferingWindow();
+        _window.Title = Loc.GetString("salvage-magnet-window-title");
         _window.OnClose += Close;
         _window.OpenCenteredLeft();
     }
index 871373e9f8fde88477866f1a20cb147c77cda7ca..f4514ac22854283a270f035d73a09a0a891b444a 100644 (file)
@@ -1,3 +1,4 @@
+using System.Linq;
 using System.Numerics;
 using System.Threading.Tasks;
 using Content.Server.Atmos;
@@ -553,54 +554,19 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
         bool emptyTiles = true)
     {
         DebugTools.Assert(count > 0);
-
-        var frontier = new ValueList<Vector2i>(32);
-        // TODO: Need poisson but crashes whenever I use moony's due to inputs or smth idk
-        // Get the total amount of groups to spawn across the entire chunk.
-        // We treat a null entity mask as requiring nothing else on the tile
-
-        spawnSet = new Dictionary<Vector2i, string?>();
-        var visited = _tilePool.Get();
-        existingEnts = new HashSet<EntityUid>();
-
-        // Pick a random tile then BFS outwards from it
-        // It will bias edge tiles significantly more but will make the CPU cry less.
-        for (var i = 0; i < count; i++)
+        var remainingTiles = _tilePool.Get();
+        var nodeEntities = new Dictionary<Vector2i, EntityUid?>();
+        var nodeMask = new Dictionary<Vector2i, string?>();
+
+        // Okay so originally we picked a random tile and BFS outwards
+        // the problem is if you somehow get a cooked frontier then it might drop entire veins
+        // hence we'll grab all valid tiles up front and use that as possible seeds.
+        // It's hella more expensive but stops issues.
+        for (var x = bounds.Left; x < bounds.Right; x++)
         {
-            var groupSize = rand.Next(layerProto.MinGroupSize, layerProto.MaxGroupSize + 1);
-            var startNodeX = rand.Next(bounds.Left, bounds.Right);
-            var startNodeY = rand.Next(bounds.Bottom, bounds.Top);
-            var startNode = new Vector2i(startNodeX, startNodeY);
-            frontier.Clear();
-            frontier.Add(startNode);
-            visited.Add(startNode);
-
-            while (groupSize >= 0 && frontier.Count > 0)
+            for (var y = bounds.Bottom; y < bounds.Top; y++)
             {
-                var frontierIndex = rand.Next(frontier.Count);
-                var node = frontier[frontierIndex];
-                frontier.RemoveSwap(frontierIndex);
-
-                // Add neighbors regardless.
-                for (var x = -1; x <= 1; x++)
-                {
-                    for (var y = -1; y <= 1; y++)
-                    {
-                        if (x != 0 && y != 0)
-                            continue;
-
-                        var neighbor = new Vector2i(node.X + x, node.Y + y);
-
-                        // Check if it's inbounds.
-                        if (!bounds.Contains(neighbor))
-                            continue;
-
-                        if (!visited.Add(neighbor))
-                            continue;
-
-                        frontier.Add(neighbor);
-                    }
-                }
+                var node = new Vector2i(x, y);
 
                 // Empty tile, skip if relevant.
                 if (!emptyTiles && (!_mapSystem.TryGetTile(grid, node, out var tile) || tile.IsEmpty))
@@ -631,21 +597,77 @@ public sealed partial class BiomeSystem : SharedBiomeSystem
                 }
 
                 DebugTools.Assert(layerProto.EntityMask.Count == 0 || !string.IsNullOrEmpty(proto));
+                remainingTiles.Add(node);
+                nodeEntities.Add(node, existing);
+                nodeMask.Add(node, proto);
+            }
+        }
 
-                // Don't fight other layers.
-                if (!spawnSet.TryAdd(node, proto))
-                    continue;
+        var frontier = new ValueList<Vector2i>(32);
+        // TODO: Need poisson but crashes whenever I use moony's due to inputs or smth idk
+        // Get the total amount of groups to spawn across the entire chunk.
+        // We treat a null entity mask as requiring nothing else on the tile
+
+        spawnSet = new Dictionary<Vector2i, string?>();
+        existingEnts = new HashSet<EntityUid>();
+
+        // Iterate the group counts and pathfind out each group.
+        for (var i = 0; i < count; i++)
+        {
+            var groupSize = rand.Next(layerProto.MinGroupSize, layerProto.MaxGroupSize + 1);
 
-                groupSize--;
+            // While we have remaining tiles keep iterating
+            while (groupSize >= 0 && remainingTiles.Count > 0)
+            {
+                var startNode = rand.PickAndTake(remainingTiles);
+                frontier.Clear();
+                frontier.Add(startNode);
 
-                if (existing != null)
+                // This essentially may lead to a vein being split in multiple areas but the count matters more than position.
+                while (frontier.Count > 0 && groupSize >= 0)
                 {
-                    existingEnts.Add(existing.Value);
+                    // Need to pick a random index so we don't just get straight lines of ores.
+                    var frontierIndex = rand.Next(frontier.Count);
+                    var node = frontier[frontierIndex];
+                    frontier.RemoveSwap(frontierIndex);
+                    remainingTiles.Remove(node);
+
+                    // Add neighbors if they're valid, worst case we add no more and pick another random seed tile.
+                    for (var x = -1; x <= 1; x++)
+                    {
+                        for (var y = -1; y <= 1; y++)
+                        {
+                            if (x != 0 && y != 0)
+                                continue;
+
+                            var neighbor = new Vector2i(node.X + x, node.Y + y);
+
+                            if (frontier.Contains(neighbor) || !remainingTiles.Contains(neighbor))
+                                continue;
+
+                            frontier.Add(neighbor);
+                        }
+                    }
+
+                    // Tile valid salad so add it.
+                    var mask = nodeMask[node];
+                    spawnSet.Add(node, mask);
+                    groupSize--;
+
+                    if (nodeEntities.TryGetValue(node, out var existing))
+                    {
+                        Del(existing);
+                    }
                 }
             }
+
+            if (groupSize > 0)
+            {
+                Log.Warning($"Found remaining group size for ore veins!");
+            }
         }
 
-        _tilePool.Return(visited);
+        _tilePool.Return(remainingTiles);
     }
 
     /// <summary>
index 26fd1c01af4772164b9613c5d4901b957615977d..e4711a5876388f27311c1670f1fd4c43ea720b0e 100644 (file)
@@ -317,20 +317,29 @@ public sealed partial class SalvageSystem
             }
         }
 
-        var magnetGridUid = _xformQuery.GetComponent(magnet.Owner).GridUid;
-        Box2 attachedBounds = Box2.Empty;
-        MapId mapId = MapId.Nullspace;
+        var magnetXform = _xformQuery.GetComponent(magnet.Owner);
+        var magnetGridUid = magnetXform.GridUid;
+        var attachedBounds = new Box2Rotated();
+        var mapId = MapId.Nullspace;
+        Angle worldAngle;
 
         if (magnetGridUid != null)
         {
             var magnetGridXform = _xformQuery.GetComponent(magnetGridUid.Value);
-            attachedBounds = _transform.GetWorldMatrix(magnetGridXform)
-                .TransformBox(_gridQuery.GetComponent(magnetGridUid.Value).LocalAABB);
+            var (gridPos, gridRot) = _transform.GetWorldPositionRotation(magnetGridXform);
+            var gridAABB = _gridQuery.GetComponent(magnetGridUid.Value).LocalAABB;
 
+            attachedBounds = new Box2Rotated(gridAABB.Translated(gridPos), gridRot, gridPos);
+
+            worldAngle = (gridRot + magnetXform.LocalRotation) - MathF.PI / 2;
             mapId = magnetGridXform.MapID;
         }
+        else
+        {
+            worldAngle = _random.NextAngle();
+        }
 
-        if (!TryGetSalvagePlacementLocation(mapId, attachedBounds, bounds!.Value, out var spawnLocation, out var spawnAngle))
+        if (!TryGetSalvagePlacementLocation(mapId, attachedBounds, bounds!.Value, worldAngle, out var spawnLocation, out var spawnAngle))
         {
             Report(magnet.Owner, MagnetChannel, "salvage-system-announcement-spawn-no-debris-available");
             _mapManager.DeleteMap(salvMap);
@@ -376,26 +385,25 @@ public sealed partial class SalvageSystem
         RaiseLocalEvent(ref active);
     }
 
-    private bool TryGetSalvagePlacementLocation(MapId mapId, Box2 attachedBounds, Box2 bounds, out MapCoordinates coords, out Angle angle)
+    private bool TryGetSalvagePlacementLocation(MapId mapId, Box2Rotated attachedBounds, Box2 bounds, Angle worldAngle, out MapCoordinates coords, out Angle angle)
     {
-        const float OffsetRadiusMin = 4f;
-        const float OffsetRadiusMax = 16f;
+        // Grid intersection only does AABB atm.
+        var attachedAABB = attachedBounds.CalcBoundingBox();
 
-        var minDistance = (attachedBounds.Height < attachedBounds.Width ? attachedBounds.Width : attachedBounds.Height) / 2f;
+        var minDistance = (attachedAABB.Height < attachedAABB.Width ? attachedAABB.Width : attachedAABB.Height) / 2f;
         var minActualDistance = bounds.Height < bounds.Width ? minDistance + bounds.Width / 2f : minDistance + bounds.Height / 2f;
 
-        var attachedCenter = attachedBounds.Center;
-
-        angle = _random.NextAngle();
+        var attachedCenter = attachedAABB.Center;
+        var fraction = 0.25f;
 
         // Thanks 20kdc
         for (var i = 0; i < 20; i++)
         {
             var randomPos = attachedCenter +
-                            _random.NextAngle().ToVec() * (minActualDistance +
-                                                           _random.NextFloat(OffsetRadiusMin, OffsetRadiusMax));
+                            worldAngle.ToVec() * (minActualDistance * fraction);
             var finalCoords = new MapCoordinates(randomPos, mapId);
 
+            angle = _random.NextAngle();
             var box2 = Box2.CenteredAround(finalCoords.Position, bounds.Size);
             var box2Rot = new Box2Rotated(box2, angle, finalCoords.Position);
 
@@ -404,7 +412,7 @@ public sealed partial class SalvageSystem
             if (_mapManager.FindGridsIntersecting(finalCoords.MapId, box2Rot).Any())
             {
                 // Bump it further and further just in case.
-                minActualDistance += 4f;
+                fraction += 0.25f;
                 continue;
             }
 
@@ -412,6 +420,7 @@ public sealed partial class SalvageSystem
             return true;
         }
 
+        angle = Angle.Zero;
         coords = MapCoordinates.Nullspace;
         return false;
     }
index 82d84fe74c4a91936966e7bb7b781340622c6281..bc9986019461aa5e1213115a3114a618ed8e3d93 100644 (file)
@@ -4,6 +4,7 @@ salvage-system-announcement-spawn-no-debris-available = No debris could be recov
 salvage-system-announcement-arrived = A piece of salvagable debris has been pulled in. Estimated hold time: {$timeLeft} seconds.
 salvage-asteroid-name = Asteroid
 
+salvage-magnet-window-title = Salvage magnet
 salvage-expedition-window-progression = Progression
 
 salvage-magnet-resources = {$resource ->
@@ -19,8 +20,10 @@ salvage-magnet-resources = {$resource ->
 
 salvage-magnet-resources-count = {$count ->
     [1] (Poor)
-    [2] (Rich)
-    [3] (Rich)
+    [2] (Moderate)
+    [3] (Moderate)
+    [4] (Rich)
+    [5] (Rich)
     *[other] (Extraordinary)
 }