-
Notifications
You must be signed in to change notification settings - Fork 188
Hotfix 22.01.2026 #1430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hotfix 22.01.2026 #1430
Changes from 5 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| using Content.Server.NPC; | ||
| using Content.Server.NPC.HTN.Preconditions; | ||
| using Content.Shared.Standing; | ||
|
|
||
| namespace Content.Server.Backmen.NPC.HTN; | ||
|
|
||
| /// <summary> | ||
| /// Checks if the owner is laydown or not | ||
| /// </summary> | ||
| public sealed partial class LaydownPrecondition : HTNPrecondition | ||
| { | ||
| private StandingStateSystem _stand = default!; | ||
|
|
||
| [ViewVariables(VVAccess.ReadWrite)] | ||
| [DataField("isDown")] | ||
| public bool IsDown = true; | ||
|
|
||
| public override void Initialize(IEntitySystemManager sysManager) | ||
| { | ||
| base.Initialize(sysManager); | ||
| _stand = sysManager.GetEntitySystem<StandingStateSystem>(); | ||
| } | ||
|
|
||
| public override bool IsMet(NPCBlackboard blackboard) | ||
| { | ||
| var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner); | ||
|
|
||
| return IsDown && _stand.IsDown(owner) || | ||
| !IsDown && !_stand.IsDown(owner); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| using Content.Server.NPC; | ||
| using Content.Server.NPC.HTN; | ||
| using Content.Server.NPC.HTN.PrimitiveTasks; | ||
| using Content.Shared.Standing; | ||
|
|
||
| namespace Content.Server.Backmen.NPC.HTN.PrimitiveTasks.Operators.Combat; | ||
|
|
||
| public sealed partial class StandOperator : HTNOperator | ||
| { | ||
| private StandingStateSystem _stand = default!; | ||
|
|
||
| [DataField("shutdownState")] | ||
| public HTNPlanState ShutdownState { get; private set; } = HTNPlanState.TaskFinished; | ||
|
|
||
| public override void Startup(NPCBlackboard blackboard) | ||
| { | ||
| base.Startup(blackboard); | ||
| var owner = blackboard.GetValue<EntityUid>(NPCBlackboard.Owner); | ||
| _stand.Stand(owner); | ||
| } | ||
|
|
||
| public override void Initialize(IEntitySystemManager sysManager) | ||
| { | ||
| base.Initialize(sysManager); | ||
| _stand = sysManager.GetEntitySystem<StandingStateSystem>(); | ||
| } | ||
|
|
||
| public override HTNOperatorStatus Update(NPCBlackboard blackboard, float frameTime) | ||
| { | ||
| return HTNOperatorStatus.Finished; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,167 @@ | ||||||||||||||||||||||||||||||||||||||||||
| using System; | ||||||||||||||||||||||||||||||||||||||||||
| using System.Linq; | ||||||||||||||||||||||||||||||||||||||||||
| using System.Numerics; | ||||||||||||||||||||||||||||||||||||||||||
| using Content.Server._Lavaland.Procedural.Components; | ||||||||||||||||||||||||||||||||||||||||||
| using Content.Shared._Lavaland.Procedural.Components; | ||||||||||||||||||||||||||||||||||||||||||
| using Content.Shared._Lavaland.Procedural.Prototypes; | ||||||||||||||||||||||||||||||||||||||||||
| using Content.Shared.Maps; | ||||||||||||||||||||||||||||||||||||||||||
| using Robust.Server.Physics; | ||||||||||||||||||||||||||||||||||||||||||
| using Robust.Shared.Map; | ||||||||||||||||||||||||||||||||||||||||||
| using Robust.Shared.Map.Components; | ||||||||||||||||||||||||||||||||||||||||||
| using Robust.Shared.Random; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| namespace Content.Server._Lavaland.Procedural.Systems; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| public sealed partial class LavalandPlanetSystem | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| [Dependency] private readonly GridFixtureSystem _gridFixture = default!; | ||||||||||||||||||||||||||||||||||||||||||
| [Dependency] private readonly ITileDefinitionManager _tileDef = default!; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| private bool LoadGridRuin( | ||||||||||||||||||||||||||||||||||||||||||
| LavalandGridRuinPrototype ruin, | ||||||||||||||||||||||||||||||||||||||||||
| Entity<LavalandMapComponent> lavaland, | ||||||||||||||||||||||||||||||||||||||||||
| Entity<LavalandPreloaderComponent> preloader, | ||||||||||||||||||||||||||||||||||||||||||
| Random random, | ||||||||||||||||||||||||||||||||||||||||||
| ref Dictionary<string, Box2> ruinsBoundsDict, | ||||||||||||||||||||||||||||||||||||||||||
| ref List<Box2> usedSpace, | ||||||||||||||||||||||||||||||||||||||||||
| ref List<Vector2> coords) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| EntityUid? spawned = null; | ||||||||||||||||||||||||||||||||||||||||||
| if (coords.Count == 0) | ||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| var coord = random.Pick(coords); | ||||||||||||||||||||||||||||||||||||||||||
| var mapXform = Transform(preloader); | ||||||||||||||||||||||||||||||||||||||||||
| Box2 ruinBox; // This is ruin box, but moved to it's correct coords on the map | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Check if we already calculated that boundary before, and if we didn't then calculate it now | ||||||||||||||||||||||||||||||||||||||||||
| if (!ruinsBoundsDict.TryGetValue(ruin.ID, out var box)) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| if (!_mapLoader.TryLoadGrid(mapXform.MapID, ruin.Path, out var spawnedBoundedGrid)) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| Log.Error($"Failed to load ruin {ruin.ID} onto dummy map, on stage of loading! AAAAA!!"); | ||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // It's not useless! | ||||||||||||||||||||||||||||||||||||||||||
| spawned = spawnedBoundedGrid.Value.Owner; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if (!_fixtureQuery.TryGetComponent(spawned, out var manager)) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| Log.Error($"Failed to load ruin {ruin.ID} onto dummy map, it doesn't have fixture component! AAAAA!!"); | ||||||||||||||||||||||||||||||||||||||||||
| Del(spawned); | ||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Actually calculate ruin bound | ||||||||||||||||||||||||||||||||||||||||||
| var transform = _physics.GetRelativePhysicsTransform(spawned.Value, preloader.Owner); | ||||||||||||||||||||||||||||||||||||||||||
| // holy shit | ||||||||||||||||||||||||||||||||||||||||||
| var bounds = (from fixture in manager.Fixtures.Values where fixture.Hard select fixture.Shape.ComputeAABB(transform, 0).Rounded(0)).ToList(); | ||||||||||||||||||||||||||||||||||||||||||
| // Round this list of boxes up to | ||||||||||||||||||||||||||||||||||||||||||
| var calculatedBox = _random.Pick(bounds); | ||||||||||||||||||||||||||||||||||||||||||
| foreach (var bound in bounds) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+56
to
+62
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: fd -t f "LavalandPlanetSystem.Grid.cs" 2>/dev/null | head -20Repository: Rxup/space-station-14 Length of output: 186 🏁 Script executed: cat -n "Content.Server/_Lavaland/Procedural/Systems/LavalandPlanetSystem.Grid.cs" | sed -n '50,70p'Repository: Rxup/space-station-14 Length of output: 1108 🏁 Script executed: # Search for _random.Pick implementation
rg "_random\.Pick" -A 5 -B 2 --type csRepository: Rxup/space-station-14 Length of output: 50378 🏁 Script executed: # Search for the Random class implementation to understand Pick behavior
rg "Pick\(" --type cs | grep -i "random\|\.pick" | head -20Repository: Rxup/space-station-14 Length of output: 2719 🏁 Script executed: # Search for existing empty collection guards in similar contexts
rg "\.Count\s*==\s*0" --type cs | head -20Repository: Rxup/space-station-14 Length of output: 2349 🏁 Script executed: # Search for Random.Pick implementation in the codebase
rg "public.*Pick\(" --type cs -A 10 | grep -A 10 "IRobustRandom\|IEnumerable"Repository: Rxup/space-station-14 Length of output: 3951 🏁 Script executed: # Check the Random extension methods that implement Pick
find . -name "*.cs" -type f -exec grep -l "SharedRandomExtensions\|RandomExtensions" {} \; 2>/dev/null | head -5Repository: Rxup/space-station-14 Length of output: 327 🏁 Script executed: # Look at the actual Random.Pick implementation
fd -t f "RandomExtensions.cs" | head -3Repository: Rxup/space-station-14 Length of output: 120 🏁 Script executed: cat -n "Content.Shared/Random/Helpers/SharedRandomExtensions.cs" | head -100Repository: Rxup/space-station-14 Length of output: 3899 🏁 Script executed: # Search for the generic Pick<T> overload that works with IList/IEnumerable
rg "public static.*Pick.*IList|public static.*Pick.*IEnumerable" --type cs -A 8 -B 2Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: cat -n "Content.Shared/Random/Helpers/SharedRandomExtensions.cs" | sed -n '100,200p'Repository: Rxup/space-station-14 Length of output: 4047 🏁 Script executed: # Search for Pick<T> with IList or similar collections
rg "Pick.*IList|Pick.*List\<" --type cs -B 2 -A 8Repository: Rxup/space-station-14 Length of output: 177 🏁 Script executed: cat -n "Content.Shared/Random/Helpers/SharedRandomExtensions.cs" | tail -100Repository: Rxup/space-station-14 Length of output: 4055 🏁 Script executed: # Search for Pick method overloads that work with lists/collections
rg "public static.*Pick" --type cs Content.Shared/Random/Helpers/SharedRandomExtensions.csRepository: Rxup/space-station-14 Length of output: 1143 🏁 Script executed: # Look in Robust.Shared for the base Pick implementation
fd -t f "RandomExtensions.cs" 2>/dev/null | xargs grep -l "Pick" 2>/dev/null | head -5Repository: Rxup/space-station-14 Length of output: 120 🏁 Script executed: # Search for Pick implementations in the entire codebase that work with lists
rg "Pick.*IList\|Pick.*IEnumerable\|Pick.*List" --type cs -B 2 -A 5 | head -100Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Look for the actual generic Pick method used on bounds (which is List<Box2>)
# Search files that might have the base implementation
find . -type f -name "*.cs" | xargs grep -l "public static.*Pick.*where.*:" | head -10Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Check robustness library or look directly in the used interfaces
rg "IRobustRandom.*Pick" --type cs -A 10 | head -150Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Search in the code for similar patterns where Pick is called on a list
rg "_random\.Pick.*bounds\|_random\.Pick.*list\|_random\.Pick.*\(\)" --type cs -B 3 -A 3Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Look for ANY Pick usage with angle brackets (generic)
rg "\.Pick\<" --type cs | head -20Repository: Rxup/space-station-14 Length of output: 145 🏁 Script executed: # Try to understand the actual usage at the problem location
cat -n "Content.Server/_Lavaland/Procedural/Systems/LavalandPlanetSystem.Grid.cs" | sed -n '50,75p'Repository: Rxup/space-station-14 Length of output: 1368 🏁 Script executed: # Search for IEnumerable/List Pick implementations across the repo
rg "Pick.*this.*IEnumerable|Pick.*this.*IList" --type cs -B 2 -A 5Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Search for any other Pick method that might handle List
rg "Pick" "Content.Shared/Random/Helpers/SharedRandomExtensions.cs" --type csRepository: Rxup/space-station-14 Length of output: 1351 🏁 Script executed: # Check if there's a generic Pick override that handles any enumerable
python3 << 'EOF'
import subprocess
import re
# Run rg to get all function definitions in the file
result = subprocess.run(
["rg", "public static.*Pick", "Content.Shared/Random/Helpers/SharedRandomExtensions.cs", "-A", "1"],
capture_output=True,
text=True
)
print("All Pick method signatures:")
print(result.stdout)
EOFRepository: Rxup/space-station-14 Length of output: 151 🏁 Script executed: # Look at what _random is - check the type definition
rg "_random" "Content.Server/_Lavaland/Procedural/Systems/LavalandPlanetSystem.Grid.cs" -B 5 | head -30Repository: Rxup/space-station-14 Length of output: 486 🏁 Script executed: # Search for IRobustRandom usage and see what methods are available
rg "IRobustRandom.*Pick" --type cs -B 5 -A 10 | head -80Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Let's check if there's a generic Pick method that works with List in the Robust.Shared library or elsewhere
# by looking at actual usages to understand the signature
rg "Pick\(.*List\|Pick\(.*bounds" --type cs -B 3 -A 3 | head -100Repository: Rxup/space-station-14 Length of output: 47 🏁 Script executed: # Search for how Pick is typically used with lists across the codebase
rg "_random\.Pick\(" --type cs -A 1 | grep -E "\.ToList|\.Values|bounds|entities" | head -30Repository: Rxup/space-station-14 Length of output: 3362 🏁 Script executed: # Try to understand by looking at test files
fd "RandomExtensionsTests" --type f | head -3Repository: Rxup/space-station-14 Length of output: 118 🏁 Script executed: cat -n "Content.Tests/Shared/Utility/RandomExtensionsTests.cs"Repository: Rxup/space-station-14 Length of output: 1568 Добавьте проверку пустого списка перед вызовом _random.Pick. Если у руины нет фиксчур с флагом Hard, список 🐛 Предложенное исправление var bounds = (from fixture in manager.Fixtures.Values where fixture.Hard select fixture.Shape.ComputeAABB(transform, 0).Rounded(0)).ToList();
+ if (bounds.Count == 0)
+ {
+ Log.Error($"Ruin {ruin.ID} has no hard fixtures to compute bounds");
+ Del(spawned.Value);
+ return false;
+ }
// Round this list of boxes up to
var calculatedBox = _random.Pick(bounds);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| calculatedBox = calculatedBox.Union(bound); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Safety measure | ||||||||||||||||||||||||||||||||||||||||||
| calculatedBox = calculatedBox.Enlarged(8f); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Add calculated box to dictionary | ||||||||||||||||||||||||||||||||||||||||||
| ruinsBoundsDict.Add(ruin.ID, calculatedBox); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Move our calculated box to correct position | ||||||||||||||||||||||||||||||||||||||||||
| var v1 = calculatedBox.BottomLeft + coord; | ||||||||||||||||||||||||||||||||||||||||||
| var v2 = calculatedBox.TopRight + coord; | ||||||||||||||||||||||||||||||||||||||||||
| ruinBox = new Box2(v1, v2); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Teleport it into place on preloader map | ||||||||||||||||||||||||||||||||||||||||||
| _transform.SetCoordinates(spawned.Value, new EntityCoordinates(preloader, coord)); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| // Why there's no method to move the Box2 around??? | ||||||||||||||||||||||||||||||||||||||||||
| var v1 = box.BottomLeft + coord; | ||||||||||||||||||||||||||||||||||||||||||
| var v2 = box.TopRight + coord; | ||||||||||||||||||||||||||||||||||||||||||
| ruinBox = new Box2(v1, v2); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // If any used boundary intersects with current boundary, return | ||||||||||||||||||||||||||||||||||||||||||
| if (usedSpace.Any(used => used.Intersects(ruinBox))) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| Log.Debug("Ruin can't be placed on it's coordinates, skipping spawn"); | ||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+89
to
+94
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n Content.Server/_Lavaland/Procedural/Systems/LavalandPlanetSystem.Grid.cs | head -120 | tail -40Repository: Rxup/space-station-14 Length of output: 186 🏁 Script executed: cat -n Content.Server/_Lavaland/Procedural/Systems/LavalandPlanetSystem.Grid.cs | head -150 | tail -80Repository: Rxup/space-station-14 Length of output: 4440 🏁 Script executed: wc -l Content.Server/_Lavaland/Procedural/Systems/LavalandPlanetSystem.Grid.csRepository: Rxup/space-station-14 Length of output: 141 🏁 Script executed: sed -n '1,150p' Content.Server/_Lavaland/Procedural/Systems/LavalandPlanetSystem.Grid.cs | cat -nRepository: Rxup/space-station-14 Length of output: 7653 Удалите временный грид при отказе размещения. При первом вычислении границ грид загружается и помещается на карту preloader (строка 79). Если проверка пересечения (строка 90) обнаружит конфликт, метод возвращает 🐛 Исправление if (usedSpace.Any(used => used.Intersects(ruinBox)))
{
Log.Debug("Ruin can't be placed on it's coordinates, skipping spawn");
+ if (spawned != null)
+ Del(spawned.Value);
return false;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Try to load it on a dummy map if it wasn't already | ||||||||||||||||||||||||||||||||||||||||||
| if (spawned == null) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| if (!_mapLoader.TryLoadGrid(mapXform.MapID, ruin.Path, out var spawnedGrid, offset: coord)) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| Log.Error($"Failed to load ruin {ruin.ID} onto dummy map, on stage of reparenting it to Lavaland! (this is really bad)"); | ||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| spawned = spawnedGrid.Value.Owner; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Set its position to Lavaland | ||||||||||||||||||||||||||||||||||||||||||
| var spawnedXForm = _xformQuery.GetComponent(spawned.Value); | ||||||||||||||||||||||||||||||||||||||||||
| _metaData.SetEntityName(spawned.Value, Loc.GetString(ruin.Name)); | ||||||||||||||||||||||||||||||||||||||||||
| _transform.SetParent(spawned.Value, spawnedXForm, lavaland); | ||||||||||||||||||||||||||||||||||||||||||
| _transform.SetCoordinates(spawned.Value, new EntityCoordinates(lavaland, spawnedXForm.Coordinates.Position.Rounded())); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Merge fixtures from lavaland grid to spawned ruin grid | ||||||||||||||||||||||||||||||||||||||||||
| if (HasComp<MapGridComponent>(lavaland.Owner)) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| var sourceGridUid = lavaland.Owner; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if (TryComp<MapGridComponent>(spawned.Value, out var spawnedGrid) && | ||||||||||||||||||||||||||||||||||||||||||
| TryComp<MapGridComponent>(sourceGridUid, out var sourceGrid) && | ||||||||||||||||||||||||||||||||||||||||||
| sourceGridUid != spawned.Value) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| try | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| // Get the position of source grid (lavaland) in local coordinates of target grid (spawned) | ||||||||||||||||||||||||||||||||||||||||||
| var sourceWorldPos = _transform.GetWorldPosition(sourceGridUid); | ||||||||||||||||||||||||||||||||||||||||||
| var localPos = _map.WorldToLocal(spawned.Value, spawnedGrid, sourceWorldPos); | ||||||||||||||||||||||||||||||||||||||||||
| var offset = (Vector2i)localPos; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Get the rotation of the target grid | ||||||||||||||||||||||||||||||||||||||||||
| var rotation = Transform(spawned.Value).LocalRotation; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Replace empty tiles in spawned grid with tiles from the same position in lavaland grid | ||||||||||||||||||||||||||||||||||||||||||
| foreach (var tile in _map.GetAllTiles(spawned.Value, spawnedGrid, false)) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| if (tile.Tile == Tile.Empty) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| // Get world position of this tile | ||||||||||||||||||||||||||||||||||||||||||
| var tileWorldPos = _map.GridTileToWorldPos(spawned.Value, spawnedGrid, tile.GridIndices); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Convert to local coordinates in lavaland grid | ||||||||||||||||||||||||||||||||||||||||||
| var lavalandTileIndices = _map.WorldToTile(sourceGridUid, sourceGrid, tileWorldPos); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Get tile from lavaland grid at this position | ||||||||||||||||||||||||||||||||||||||||||
| if (_map.TryGetTileRef(sourceGridUid, sourceGrid, lavalandTileIndices, out var lavalandTile) && | ||||||||||||||||||||||||||||||||||||||||||
| !lavalandTile.Tile.IsEmpty) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| _map.SetTile(spawned.Value, spawnedGrid, tile.GridIndices, lavalandTile.Tile); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| _gridFixture.Merge(sourceGridUid, spawned.Value, offset, rotation); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| catch (Exception ex) | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| Log.Error($"Failed to merge fixtures for ruin {ruin.ID}: {ex}"); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // yaaaaaaaaaaaaaaaay | ||||||||||||||||||||||||||||||||||||||||||
| usedSpace.Add(ruinBox); | ||||||||||||||||||||||||||||||||||||||||||
| coords.Remove(coord); | ||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: Rxup/space-station-14
Length of output: 702
🏁 Script executed:
Repository: Rxup/space-station-14
Length of output: 3522
Упростите вызов, используя значение параметра по умолчанию.
Параметр
removeWoundsв методеForceRestoreBodyимеет значение по умолчаниюtrue. Вызов_bodySystem.ForceRestoreBody(target, true)на строке 276 можно упростить до_bodySystem.ForceRestoreBody(target)без явной передачи параметра, совпадающего с умолчанием.Размещение вызова вне блока проверки нервной системы является намеренным — метод применяется ко всем зомбифицированным сущностям. Параметр
removeWoundsдостаточно ясно описывает назначение.🤖 Prompt for AI Agents