Salvage dungeons (#14520)

This commit is contained in:
metalgearsloth
2023-03-10 16:41:22 +11:00
committed by GitHub
parent 214ca06997
commit 6157dfa3c0
145 changed files with 24649 additions and 396 deletions

View File

@@ -109,6 +109,7 @@ namespace Content.Client.Entry
_prototypeManager.RegisterIgnore("metabolizerType"); _prototypeManager.RegisterIgnore("metabolizerType");
_prototypeManager.RegisterIgnore("metabolismGroup"); _prototypeManager.RegisterIgnore("metabolismGroup");
_prototypeManager.RegisterIgnore("salvageMap"); _prototypeManager.RegisterIgnore("salvageMap");
_prototypeManager.RegisterIgnore("salvageFaction");
_prototypeManager.RegisterIgnore("gamePreset"); _prototypeManager.RegisterIgnore("gamePreset");
_prototypeManager.RegisterIgnore("gameRule"); _prototypeManager.RegisterIgnore("gameRule");
_prototypeManager.RegisterIgnore("worldSpell"); _prototypeManager.RegisterIgnore("worldSpell");

View File

@@ -29,6 +29,9 @@ namespace Content.Client.IconSmoothing
[ViewVariables(VVAccess.ReadWrite), DataField("base")] [ViewVariables(VVAccess.ReadWrite), DataField("base")]
public string StateBase { get; } = string.Empty; public string StateBase { get; } = string.Empty;
[DataField("shader", customTypeSerializer:typeof(PrototypeIdSerializer<ShaderPrototype>))]
public string? Shader;
/// <summary> /// <summary>
/// Mode that controls how the icon should be selected. /// Mode that controls how the icon should be selected.
/// </summary> /// </summary>

View File

@@ -55,6 +55,14 @@ namespace Content.Client.IconSmoothing
sprite.LayerSetDirOffset(CornerLayers.NW, DirectionOffset.Flip); sprite.LayerSetDirOffset(CornerLayers.NW, DirectionOffset.Flip);
sprite.LayerMapSet(CornerLayers.SW, sprite.AddLayerState(state0)); sprite.LayerMapSet(CornerLayers.SW, sprite.AddLayerState(state0));
sprite.LayerSetDirOffset(CornerLayers.SW, DirectionOffset.Clockwise); sprite.LayerSetDirOffset(CornerLayers.SW, DirectionOffset.Clockwise);
if (component.Shader != null)
{
sprite.LayerSetShader(CornerLayers.SE, component.Shader);
sprite.LayerSetShader(CornerLayers.NE, component.Shader);
sprite.LayerSetShader(CornerLayers.NW, component.Shader);
sprite.LayerSetShader(CornerLayers.SW, component.Shader);
}
} }
private void OnShutdown(EntityUid uid, IconSmoothComponent component, ComponentShutdown args) private void OnShutdown(EntityUid uid, IconSmoothComponent component, ComponentShutdown args)

View File

@@ -74,8 +74,6 @@ namespace Content.Client.Lobby.UI
AddChild(vBox); AddChild(vBox);
UpdateUI(); UpdateUI();
_preferencesManager.OnServerDataLoaded += UpdateUI;
} }
public Button CharacterSetupButton { get; } public Button CharacterSetupButton { get; }
@@ -128,7 +126,7 @@ namespace Content.Client.Lobby.UI
_viewBox.AddChild(viewWest); _viewBox.AddChild(viewWest);
_viewBox.AddChild(viewEast); _viewBox.AddChild(viewEast);
_summaryLabel.Text = selectedCharacter.Summary; _summaryLabel.Text = selectedCharacter.Summary;
EntitySystem.Get<HumanoidAppearanceSystem>().LoadProfile(_previewDummy.Value, selectedCharacter); _entityManager.System<HumanoidAppearanceSystem>().LoadProfile(_previewDummy.Value, selectedCharacter);
GiveDummyJobClothes(_previewDummy.Value, selectedCharacter); GiveDummyJobClothes(_previewDummy.Value, selectedCharacter);
} }
} }

View File

@@ -235,7 +235,7 @@ namespace Content.Client.Parallax
for (var x = 0; x < bitmap.Width; x++) for (var x = 0; x < bitmap.Width; x++)
{ {
// Do noise calculations. // Do noise calculations.
var noiseVal = MathF.Min(1, MathF.Max(0, (noise.GetNoiseTiled(x, y) + 1) / 2)); var noiseVal = MathF.Min(1, MathF.Max(0, (noise.GetNoise(x, y) + 1) / 2));
// Threshold // Threshold
noiseVal = MathF.Max(0, noiseVal - Threshold); noiseVal = MathF.Max(0, noiseVal - Threshold);
@@ -462,7 +462,7 @@ namespace Content.Client.Parallax
var y = random.Next(0, buffer.Height); var y = random.Next(0, buffer.Height);
// Grab noise at this point. // Grab noise at this point.
var noiseVal = MathF.Min(1, MathF.Max(0, (noise.GetNoiseTiled(x, y) + 1) / 2)); var noiseVal = MathF.Min(1, MathF.Max(0, (noise.GetNoise(x, y) + 1) / 2));
// Threshold // Threshold
noiseVal = MathF.Max(0, noiseVal - MaskThreshold); noiseVal = MathF.Max(0, noiseVal - MaskThreshold);
noiseVal *= threshVal; noiseVal *= threshVal;

View File

@@ -0,0 +1,8 @@
using Content.Shared.Salvage;
namespace Content.Client.Salvage;
public sealed class SalvageSystem : SharedSalvageSystem
{
}

View File

@@ -0,0 +1,47 @@
using Content.Shared.Salvage;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
namespace Content.Client.Salvage.UI;
[UsedImplicitly]
public sealed class SalvageExpeditionConsoleBoundUserInterface : BoundUserInterface
{
private SalvageExpeditionWindow? _window;
public SalvageExpeditionConsoleBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
base.Open();
_window = new SalvageExpeditionWindow();
_window.ClaimMission += index =>
{
SendMessage(new ClaimSalvageMessage()
{
Index = index,
});
};
_window.OnClose += Close;
_window?.OpenCenteredLeft();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_window?.Dispose();
_window = null;
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (state is not SalvageExpeditionConsoleState current)
return;
_window?.UpdateState(current);
}
}

View File

@@ -0,0 +1,23 @@
<controls:FancyWindow xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
Title="{Loc 'Salvage expeditions'}"
MinSize="800 360">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal">
<Label Name="NextOfferLabel"
Text="Next offer:"
Margin="5"></Label>
<ProgressBar Name="NextOfferBar"
HorizontalExpand="True"
MinValue="0"
MaxValue="1"
SetHeight="25"/>
<Label Name="NextOfferText" Text="0.00"
Margin="5"/>
</BoxContainer>
<controls:HLine Color="#404040" Thickness="2" Margin="0 5 0 5"/>
<BoxContainer Name="Container"
Orientation="Horizontal"
Margin="5 0 5 0"/>
</BoxContainer>
</controls:FancyWindow>

View File

@@ -0,0 +1,334 @@
using Content.Client.Computer;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Procedural;
using Content.Shared.Procedural.Loot;
using Content.Shared.Procedural.Rewards;
using Content.Shared.Random;
using Content.Shared.Random.Helpers;
using Content.Shared.Salvage;
using Content.Shared.Salvage.Expeditions;
using Content.Shared.Salvage.Expeditions.Structure;
using Content.Shared.Shuttles.BUIStates;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
namespace Content.Client.Salvage.UI;
[GenerateTypedNameReferences]
public sealed partial class SalvageExpeditionWindow : FancyWindow,
IComputerWindow<EmergencyConsoleBoundUserInterfaceState>
{
private readonly IGameTiming _timing;
private readonly IPrototypeManager _prototype;
private readonly SharedSalvageSystem _salvage;
public event Action<ushort>? ClaimMission;
private bool _claimed;
private TimeSpan _nextOffer;
public SalvageExpeditionWindow()
{
RobustXamlLoader.Load(this);
_timing = IoCManager.Resolve<IGameTiming>();
_prototype = IoCManager.Resolve<IPrototypeManager>();
_salvage = IoCManager.Resolve<IEntityManager>().EntitySysManager.GetEntitySystem<SharedSalvageSystem>();
}
public void UpdateState(SalvageExpeditionConsoleState state)
{
_claimed = state.Claimed;
_nextOffer = state.NextOffer;
Container.DisposeAllChildren();
for (var i = 0; i < state.Missions.Count; i++)
{
// TODO: Make this XAML
var mission = state.Missions[i];
var config = _prototype.Index<SalvageExpeditionPrototype>(mission.Config);
var dungeonConfig = _prototype.Index<DungeonConfigPrototype>(config.DungeonConfigPrototype);
var faction = SharedSalvageSystem.GetFaction(config.Factions, mission.Seed);
var factionConfig = _prototype.Index<SalvageFactionPrototype>(faction);
// If we ever need this on server then move it
var missionDesc = string.Empty;
var missionDetails = string.Empty;
switch (config.Mission)
{
case SalvageStructure structure:
var structureConfig = (SalvageStructureFaction) factionConfig.Configs[mission.Config];
missionDesc = "Demolition";
// TODO:
missionDetails = $"Destroy {SharedSalvageSystem.GetStructureCount(structure, mission.Seed)} {_prototype.Index<EntityPrototype>(structureConfig.Spawn).Name} structures.";
break;
default:
throw new NotImplementedException();
}
// Mission
var missionStripe = new StripeBack()
{
Margin = new Thickness(0f, -5f, 0f, 0f)
};
missionStripe.AddChild(new Label()
{
Text = missionDesc,
HorizontalAlignment = HAlignment.Center,
Margin = new Thickness(0f, 5f, 0f, 5f),
});
var lBox = new BoxContainer()
{
Orientation = BoxContainer.LayoutOrientation.Vertical
};
// Difficulty
// Details
lBox.AddChild(new Label()
{
Text = $"Difficulty:"
});
var difficultyColor = StyleNano.NanoGold;
switch (config.DifficultyRating)
{
case DifficultyRating.None:
difficultyColor = StyleNano.ButtonColorDefault;
break;
case DifficultyRating.Minor:
difficultyColor = StyleNano.GoodGreenFore;
break;
case DifficultyRating.Moderate:
difficultyColor = StyleNano.ConcerningOrangeFore;
break;
default:
throw new ArgumentOutOfRangeException();
}
lBox.AddChild(new Label
{
Text = config.DifficultyRating.ToString(),
FontColorOverride = difficultyColor,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
// Details
lBox.AddChild(new Label
{
Text = $"Details:"
});
lBox.AddChild(new Label
{
Text = missionDetails,
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
// Details
lBox.AddChild(new Label
{
Text = $"Hostiles:"
});
lBox.AddChild(new Label
{
Text = faction,
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
// Duration
lBox.AddChild(new Label
{
Text = $"Duration:"
});
lBox.AddChild(new Label
{
Text = mission.Duration.ToString(),
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
// Biome
lBox.AddChild(new Label
{
Text = "Biome:"
});
lBox.AddChild(new Label
{
Text = _prototype.Index<BiomePrototype>(config.Biome).Description,
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
// Environment
lBox.AddChild(new Label
{
Text = "Environment:"
});
lBox.AddChild(new Label
{
Text = config.Description,
FontColorOverride = StyleNano.NanoGold,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
// Modifiers
// TODO
// Rewards
lBox.AddChild(new Label()
{
Text = $"Reward:"
});
var salvageReward = SharedSalvageSystem.GetReward(_prototype.Index<WeightedRandomPrototype>(config.Reward), mission.Seed, _prototype);
var difficulty = config.DifficultyRating;
var rewardDesc = string.Empty;
switch (salvageReward)
{
case BankReward bank:
rewardDesc = $"Bank payment of {(int) (bank.Amount * SharedSalvageSystem.GetDifficultyModifier(difficulty))}";
break;
default:
throw new ArgumentOutOfRangeException();
}
lBox.AddChild(new Label()
{
Text = rewardDesc,
FontColorOverride = StyleNano.GoodGreenFore,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
lBox.AddChild(new Label()
{
Text = $"Materials:"
});
if (config.Loots.Count == 0)
{
lBox.AddChild(new Label()
{
Text = "N/A",
FontColorOverride = StyleNano.ConcerningOrangeFore,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
}
else
{
foreach (var lootProto in SharedSalvageSystem.GetLoot(config.Loots, mission.Seed, _prototype))
{
lBox.AddChild(new Label()
{
Text = lootProto.Description,
FontColorOverride = StyleNano.ConcerningOrangeFore,
HorizontalAlignment = HAlignment.Left,
Margin = new Thickness(0f, 0f, 0f, 5f),
});
}
}
// Claim
var claimButton = new Button()
{
HorizontalExpand = true,
Pressed = state.ActiveMission == mission.Index,
ToggleMode = true,
Disabled = state.Claimed,
};
claimButton.Label.Margin = new Thickness(0f, 5f);
claimButton.OnPressed += args =>
{
ClaimMission?.Invoke(mission.Index);
};
if (state.ActiveMission == mission.Index)
{
claimButton.Text = "Claimed";
claimButton.AddStyleClass(StyleBase.ButtonCaution);
}
else
{
claimButton.Text = "Claim";
}
// TODO: Fix this copypaste bullshit
var box = new PanelContainer()
{
PanelOverride = new StyleBoxFlat(new Color(30, 30, 34)),
HorizontalExpand = true,
Margin = new Thickness(5f, 0f),
Children =
{
new BoxContainer()
{
Orientation = BoxContainer.LayoutOrientation.Vertical,
Children =
{
missionStripe,
lBox,
claimButton,
},
Margin = new Thickness(5f, 5f)
}
}
};
LayoutContainer.SetAnchorPreset(box, LayoutContainer.LayoutPreset.Wide);
Container.AddChild(box);
}
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
if (_claimed)
{
NextOfferBar.Value = 0f;
NextOfferText.Text = "N/A";
return;
}
var remaining = _nextOffer - _timing.CurTime;
if (remaining < TimeSpan.Zero)
{
NextOfferBar.Value = 1f;
NextOfferText.Text = "00:00";
}
else
{
NextOfferBar.Value = 1f - (float) (remaining / SharedSalvageSystem.MissionCooldown);
NextOfferText.Text = $"{remaining.Minutes:00}:{remaining.Seconds:00}";
}
}
}

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Content.Server.Procedural;
using Content.Shared.Procedural;
using NUnit.Framework;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
namespace Content.IntegrationTests.Tests.Procedural;
[TestOf(typeof(DungeonSystem))]
public sealed class DungeonTests
{
[Test]
public async Task TestDungeonRoomPackBounds()
{
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true});
var protoManager = pairTracker.Pair.Server.ResolveDependency<IPrototypeManager>();
await pairTracker.Pair.Server.WaitAssertion(() =>
{
var sizes = new HashSet<Vector2i>();
foreach (var proto in protoManager.EnumeratePrototypes<DungeonRoomPrototype>())
{
sizes.Add(proto.Size);
sizes.Add(new Vector2i(proto.Size.Y, proto.Size.X));
}
foreach (var pack in protoManager.EnumeratePrototypes<DungeonRoomPackPrototype>())
{
var rooms = new List<Box2>();
for (var i = 0; i < pack.Rooms.Count; i++)
{
var room = pack.Rooms[i];
var bounds = (Box2) room;
for (var j = 0; j < rooms.Count; j++)
{
var existing = rooms[j];
Assert.That(!existing.Intersects(bounds), $"Found overlapping rooms {i} and {j} in DungeonRoomPack {pack.ID}");
}
rooms.Add(bounds);
// Inclusive of upper bounds as it's the edge
Assert.That(room.Left >= 0 &&
room.Bottom >= 0 &&
room.Right <= pack.Size.X &&
room.Top <= pack.Size.Y, $"Found invalid room {room} on DungeonRoomPack {pack.ID}");
// Assert that anything exists at this size
var rotated = new Vector2i(room.Size.Y, room.Size.X);
Assert.That(sizes.Contains(room.Size) || sizes.Contains(rotated), $"Didn't find any dungeon room prototypes for {room.Size} on {pack.ID} index {i}");
}
}
});
await pairTracker.CleanReturnAsync();
}
[Test]
public async Task TestDungeonPresets()
{
await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true});
var protoManager = pairTracker.Pair.Server.ResolveDependency<IPrototypeManager>();
await pairTracker.Pair.Server.WaitAssertion(() =>
{
var sizes = new HashSet<Vector2i>();
foreach (var pack in protoManager.EnumeratePrototypes<DungeonRoomPackPrototype>())
{
sizes.Add(pack.Size);
sizes.Add(new Vector2i(pack.Size.Y, pack.Size.X));
}
foreach (var preset in protoManager.EnumeratePrototypes<DungeonPresetPrototype>())
{
for (var i = 0; i < preset.RoomPacks.Count; i++)
{
var pack = preset.RoomPacks[i];
// Assert that anything exists at this size
var rotated = new Vector2i(pack.Size.Y, pack.Size.X);
Assert.That(sizes.Contains(pack.Size) || sizes.Contains(rotated), $"Didn't find any dungeon room prototypes for {pack.Size} for {preset.ID} index {i}");
}
}
});
await pairTracker.CleanReturnAsync();
}
}

View File

@@ -7,6 +7,11 @@ namespace Content.Server.CPUJob.JobQueues.Queues
{ {
private readonly IStopwatch _stopwatch; private readonly IStopwatch _stopwatch;
public JobQueue(double maxTime) : this(new Stopwatch())
{
MaxTime = maxTime;
}
public JobQueue() : this(new Stopwatch()) {} public JobQueue() : this(new Stopwatch()) {}
public JobQueue(IStopwatch stopwatch) public JobQueue(IStopwatch stopwatch)

View File

@@ -2,6 +2,7 @@ using Content.Server.Cargo.Components;
using Content.Server.Station.Systems; using Content.Server.Station.Systems;
using Content.Shared.Cargo; using Content.Shared.Cargo;
using Content.Shared.Containers.ItemSlots; using Content.Shared.Containers.ItemSlots;
using JetBrains.Annotations;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
namespace Content.Server.Cargo.Systems; namespace Content.Server.Cargo.Systems;
@@ -44,9 +45,20 @@ public sealed partial class CargoSystem : SharedCargoSystem
UpdateTelepad(frameTime); UpdateTelepad(frameTime);
} }
// please don't delete this thank you [PublicAPI]
public void UpdateBankAccount(StationBankAccountComponent component, int balanceAdded) public void UpdateBankAccount(StationBankAccountComponent component, int balanceAdded)
{ {
component.Balance += balanceAdded; component.Balance += balanceAdded;
// TODO: Code bad
foreach (var comp in EntityQuery<CargoOrderConsoleComponent>())
{
if (!_uiSystem.IsUiOpen(comp.Owner, CargoConsoleUiKey.Orders)) continue;
var station = _station.GetOwningStation(comp.Owner);
if (station != component.Owner)
continue;
UpdateOrderState(comp, station);
}
} }
} }

View File

@@ -10,6 +10,7 @@ using Content.Shared.Pulling.Components;
using Content.Shared.Tools; using Content.Shared.Tools;
using Content.Shared.Tools.Components; using Content.Shared.Tools.Components;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Components;
namespace Content.Server.Construction namespace Content.Server.Construction
@@ -99,7 +100,12 @@ namespace Content.Server.Construction
return false; return false;
var tileIndices = grid.TileIndicesFor(coordinates); var tileIndices = grid.TileIndicesFor(coordinates);
var enumerator = grid.GetAnchoredEntitiesEnumerator(tileIndices); return TileFree(grid, tileIndices, anchorBody.CollisionLayer, anchorBody.CollisionMask);
}
public bool TileFree(MapGridComponent grid, Vector2i gridIndices, int collisionLayer = 0, int collisionMask = 0)
{
var enumerator = grid.GetAnchoredEntitiesEnumerator(gridIndices);
var bodyQuery = GetEntityQuery<PhysicsComponent>(); var bodyQuery = GetEntityQuery<PhysicsComponent>();
while (enumerator.MoveNext(out var ent)) while (enumerator.MoveNext(out var ent))
@@ -111,8 +117,8 @@ namespace Content.Server.Construction
continue; continue;
} }
if ((body.CollisionMask & anchorBody.CollisionLayer) != 0x0 || if ((body.CollisionMask & collisionLayer) != 0x0 ||
(body.CollisionLayer & anchorBody.CollisionMask) != 0x0) (body.CollisionLayer & collisionMask) != 0x0)
{ {
return false; return false;
} }

View File

@@ -319,6 +319,33 @@ namespace Content.Server.Decals
return decalIds; return decalIds;
} }
public HashSet<(uint Index, Decal Decal)> GetDecalsIntersecting(EntityUid gridUid, Box2 bounds, DecalGridComponent? component = null)
{
var decalIds = new HashSet<(uint, Decal)>();
var chunkCollection = ChunkCollection(gridUid, component);
if (chunkCollection == null)
return decalIds;
var chunks = new ChunkIndicesEnumerator(bounds, ChunkSize);
while (chunks.MoveNext(out var chunkOrigin))
{
if (!chunkCollection.TryGetValue(chunkOrigin.Value, out var chunk))
continue;
foreach (var (id, decal) in chunk.Decals)
{
if (!bounds.Contains(decal.Coordinates))
continue;
decalIds.Add((id, decal));
}
}
return decalIds;
}
/// <summary> /// <summary>
/// Changes a decals position. Note this will actually result in a new decal being created, possibly on a new grid or chunk. /// Changes a decals position. Note this will actually result in a new decal being created, possibly on a new grid or chunk.
/// </summary> /// </summary>

View File

@@ -1,3 +1,4 @@
using Content.Shared.Gravity;
using Content.Shared.NPC; using Content.Shared.NPC;
namespace Content.Server.NPC.Pathfinding; namespace Content.Server.NPC.Pathfinding;
@@ -45,7 +46,8 @@ public sealed partial class PathfindingSystem
var modifier = 1f; var modifier = 1f;
// TODO // TODO
if ((end.Data.Flags & PathfindingBreadcrumbFlag.Space) != 0x0) if ((end.Data.Flags & PathfindingBreadcrumbFlag.Space) != 0x0 &&
(!TryComp<GravityComponent>(end.GraphUid, out var gravity) || !gravity.Enabled))
{ {
return 0f; return 0f;
} }

View File

@@ -16,12 +16,25 @@ public sealed partial class PathfindingSystem
return dx + dy; return dx + dy;
} }
public float ManhattanDistance(Vector2i start, Vector2i end)
{
var distance = end - start;
return Math.Abs(distance.X) + Math.Abs(distance.Y);
}
public float OctileDistance(PathPoly start, PathPoly end) public float OctileDistance(PathPoly start, PathPoly end)
{ {
var (dx, dy) = GetDiff(start, end); var (dx, dy) = GetDiff(start, end);
return dx + dy + (1.41f - 2) * Math.Min(dx, dy); return dx + dy + (1.41f - 2) * Math.Min(dx, dy);
} }
public float OctileDistance(Vector2i start, Vector2i end)
{
var diff = start - end;
var ab = Vector2.Abs(diff);
return ab.X + ab.Y + (1.41f - 2) * Math.Min(ab.X, ab.Y);
}
private Vector2 GetDiff(PathPoly start, PathPoly end) private Vector2 GetDiff(PathPoly start, PathPoly end)
{ {
var startPos = start.Box.Center; var startPos = start.Box.Center;

View File

@@ -32,7 +32,7 @@ public sealed partial class PathfindingSystem
/// If true, UpdateGrid() will not process grids. /// If true, UpdateGrid() will not process grids.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Useful if something like a large explosion is in the process of shredding the grid, as it avoids uneccesary /// Useful if something like a large explosion is in the process of shredding the grid, as it avoids unneccesary
/// updating. /// updating.
/// </remarks> /// </remarks>
public bool PauseUpdating = false; public bool PauseUpdating = false;
@@ -232,11 +232,6 @@ public sealed partial class PathfindingSystem
comp.DirtyChunks.Clear(); comp.DirtyChunks.Clear();
} }
#if DEBUG
if (updateCount > 0)
_sawmill.Debug($"Updated {updateCount} nav chunks in {_stopwatch.Elapsed.TotalMilliseconds:0.000}ms");
#endif
} }
private bool IsBodyRelevant(PhysicsComponent body) private bool IsBodyRelevant(PhysicsComponent body)

View File

@@ -0,0 +1,74 @@
namespace Content.Server.NPC.Pathfinding;
public sealed partial class PathfindingSystem
{
/// <summary>
/// Finds a generic path from start to end.
/// </summary>
public List<Vector2i> GetPath(Vector2i start, Vector2i end, bool diagonal = false)
{
if (start == end)
{
return new List<Vector2i>();
}
var frontier = new PriorityQueue<Vector2i, float>();
frontier.Enqueue(start, 0f);
var cameFrom = new Dictionary<Vector2i, Vector2i>();
var node = start;
while (frontier.TryDequeue(out node, out _))
{
if (node == end)
{
break;
}
if (diagonal)
{
for (var i = 0; i < 8; i++)
{
var direction = (DirectionFlag) i;
var neighbor = node + direction.AsDir().ToIntVec();
if (!cameFrom.TryAdd(neighbor, node))
continue;
var gScore = OctileDistance(neighbor, end);
frontier.Enqueue(neighbor, gScore);
}
}
else
{
for (var i = 0; i < 4; i++)
{
var direction = (DirectionFlag) Math.Pow(2, i);
var neighbor = node + direction.AsDir().ToIntVec();
if (!cameFrom.TryAdd(neighbor, node))
continue;
frontier.Enqueue(neighbor, ManhattanDistance(neighbor, end));
}
}
}
if (node != end)
{
return new List<Vector2i>();
}
var path = new List<Vector2i>();
do
{
path.Add(node);
var before = cameFrom[node];
node = before;
} while (node != start);
path.Add(start);
path.Reverse();
return path;
}
}

View File

@@ -33,6 +33,7 @@ public sealed class BiomeSystem : SharedBiomeSystem
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<BiomeComponent, ComponentStartup>(OnBiomeStartup);
SubscribeLocalEvent<BiomeComponent, MapInitEvent>(OnBiomeMapInit); SubscribeLocalEvent<BiomeComponent, MapInitEvent>(OnBiomeMapInit);
_configManager.OnValueChanged(CVars.NetMaxUpdateRange, SetLoadRange, true); _configManager.OnValueChanged(CVars.NetMaxUpdateRange, SetLoadRange, true);
} }
@@ -50,9 +51,15 @@ public sealed class BiomeSystem : SharedBiomeSystem
_loadArea = new Box2(-_loadRange, -_loadRange, _loadRange, _loadRange); _loadArea = new Box2(-_loadRange, -_loadRange, _loadRange, _loadRange);
} }
private void OnBiomeStartup(EntityUid uid, BiomeComponent component, ComponentStartup args)
{
component.Noise.SetSeed(component.Seed);
}
private void OnBiomeMapInit(EntityUid uid, BiomeComponent component, MapInitEvent args) private void OnBiomeMapInit(EntityUid uid, BiomeComponent component, MapInitEvent args)
{ {
component.Seed = _random.Next(); component.Seed = _random.Next();
component.Noise.SetSeed(component.Seed);
Dirty(component); Dirty(component);
} }
@@ -97,7 +104,7 @@ public sealed class BiomeSystem : SharedBiomeSystem
while (loadBiomes.MoveNext(out var biome, out var grid)) while (loadBiomes.MoveNext(out var biome, out var grid))
{ {
var noise = new FastNoise(biome.Seed); var noise = biome.Noise;
var gridUid = grid.Owner; var gridUid = grid.Owner;
// Load new chunks // Load new chunks
@@ -124,7 +131,7 @@ public sealed class BiomeSystem : SharedBiomeSystem
BiomeComponent component, BiomeComponent component,
EntityUid gridUid, EntityUid gridUid,
MapGridComponent grid, MapGridComponent grid,
FastNoise noise, FastNoiseLite noise,
EntityQuery<TransformComponent> xformQuery) EntityQuery<TransformComponent> xformQuery)
{ {
var active = _activeChunks[component]; var active = _activeChunks[component];
@@ -147,7 +154,7 @@ public sealed class BiomeSystem : SharedBiomeSystem
EntityUid gridUid, EntityUid gridUid,
MapGridComponent grid, MapGridComponent grid,
Vector2i chunk, Vector2i chunk,
FastNoise noise, FastNoiseLite noise,
BiomePrototype prototype, BiomePrototype prototype,
List<(Vector2i, Tile)> tiles, List<(Vector2i, Tile)> tiles,
EntityQuery<TransformComponent> xformQuery) EntityQuery<TransformComponent> xformQuery)
@@ -252,7 +259,7 @@ public sealed class BiomeSystem : SharedBiomeSystem
} }
} }
private void UnloadChunks(BiomeComponent component, EntityUid gridUid, MapGridComponent grid, FastNoise noise) private void UnloadChunks(BiomeComponent component, EntityUid gridUid, MapGridComponent grid, FastNoiseLite noise)
{ {
var active = _activeChunks[component]; var active = _activeChunks[component];
List<(Vector2i, Tile)>? tiles = null; List<(Vector2i, Tile)>? tiles = null;
@@ -268,7 +275,7 @@ public sealed class BiomeSystem : SharedBiomeSystem
} }
} }
private void UnloadChunk(BiomeComponent component, EntityUid gridUid, MapGridComponent grid, Vector2i chunk, FastNoise noise, List<(Vector2i, Tile)> tiles) private void UnloadChunk(BiomeComponent component, EntityUid gridUid, MapGridComponent grid, Vector2i chunk, FastNoiseLite noise, List<(Vector2i, Tile)> tiles)
{ {
// Reverse order to loading // Reverse order to loading
var prototype = ProtoManager.Index<BiomePrototype>(component.BiomePrototype); var prototype = ProtoManager.Index<BiomePrototype>(component.BiomePrototype);

View File

@@ -14,7 +14,7 @@ namespace Content.Server.Pinpointer
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<PinpointerComponent, ActivateInWorldEvent>(OnActivate); SubscribeLocalEvent<PinpointerComponent, ActivateInWorldEvent>(OnActivate);
SubscribeLocalEvent<HyperspaceJumpCompletedEvent>(OnLocateTarget); SubscribeLocalEvent<FTLCompletedEvent>(OnLocateTarget);
} }
private void OnActivate(EntityUid uid, PinpointerComponent component, ActivateInWorldEvent args) private void OnActivate(EntityUid uid, PinpointerComponent component, ActivateInWorldEvent args)
@@ -23,7 +23,7 @@ namespace Content.Server.Pinpointer
LocateTarget(uid, component); LocateTarget(uid, component);
} }
private void OnLocateTarget(HyperspaceJumpCompletedEvent ev) private void OnLocateTarget(ref FTLCompletedEvent ev)
{ {
// This feels kind of expensive, but it only happens once per hyperspace jump // This feels kind of expensive, but it only happens once per hyperspace jump

View File

@@ -0,0 +1,13 @@
using Robust.Shared.Utility;
namespace Content.Server.Procedural;
/// <summary>
/// Added to pre-loaded maps for dungeon templates.
/// </summary>
[RegisterComponent]
public sealed class DungeonAtlasTemplateComponent : Component
{
[DataField("path", required: true)]
public ResourcePath? Path;
}

View File

@@ -0,0 +1,429 @@
using System.Threading.Tasks;
using Content.Shared.Decals;
using Content.Shared.Procedural;
using Content.Shared.Procedural.DungeonGenerators;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Random;
using Robust.Shared.Utility;
namespace Content.Server.Procedural;
public sealed partial class DungeonJob
{
private async Task<Dungeon> GeneratePrefabDungeon(PrefabDunGen prefab, EntityUid gridUid, MapGridComponent grid, int seed)
{
var random = new Random(seed);
var preset = prefab.Presets[random.Next(prefab.Presets.Count)];
var gen = _prototype.Index<DungeonPresetPrototype>(preset);
var dungeonRotation = _dungeon.GetDungeonRotation(seed);
var dungeonTransform = Matrix3.CreateTransform(_position, dungeonRotation);
var roomPackProtos = new Dictionary<Vector2i, List<DungeonRoomPackPrototype>>();
var externalNodes = new Dictionary<DungeonRoomPackPrototype, HashSet<Vector2i>>();
var fallbackTile = new Tile(_tileDefManager[prefab.Tile].TileId);
foreach (var pack in _prototype.EnumeratePrototypes<DungeonRoomPackPrototype>())
{
var size = pack.Size;
var sizePacks = roomPackProtos.GetOrNew(size);
sizePacks.Add(pack);
// Determine external connections; these are only valid when adjacent to a room node.
// We use this later to determine which room packs connect to each other
var nodes = new HashSet<Vector2i>();
externalNodes.Add(pack, nodes);
foreach (var room in pack.Rooms)
{
var rator = new Box2iEdgeEnumerator(room, false);
while (rator.MoveNext(out var index))
{
nodes.Add(index);
}
}
}
// Need to sort to make the RNG deterministic (at least without prototype changes).
foreach (var roomA in roomPackProtos.Values)
{
roomA.Sort((x, y) =>
string.Compare(x.ID, y.ID, StringComparison.Ordinal));
}
var roomProtos = new Dictionary<Vector2i, List<DungeonRoomPrototype>>();
foreach (var proto in _prototype.EnumeratePrototypes<DungeonRoomPrototype>())
{
var whitelisted = false;
foreach (var tag in prefab.RoomWhitelist)
{
if (proto.Tags.Contains(tag))
{
whitelisted = true;
break;
}
}
if (!whitelisted)
continue;
var size = proto.Size;
var sizeRooms = roomProtos.GetOrNew(size);
sizeRooms.Add(proto);
}
foreach (var roomA in roomProtos.Values)
{
roomA.Sort((x, y) =>
string.Compare(x.ID, y.ID, StringComparison.Ordinal));
}
// First we gather all of the edges for each roompack in the preset
// This allows us to determine which ones should connect from being adjacent
var edges = new HashSet<Vector2i>[gen.RoomPacks.Count];
for (var i = 0; i < gen.RoomPacks.Count; i++)
{
var pack = gen.RoomPacks[i];
var nodes = new HashSet<Vector2i>(pack.Width + 2 + pack.Height);
var rator = new Box2iEdgeEnumerator(pack, false);
while (rator.MoveNext(out var index))
{
nodes.Add(index);
}
edges[i] = nodes;
}
// Build up edge groups between each pack.
var connections = new Dictionary<int, Dictionary<int, HashSet<Vector2i>>>();
for (var i = 0; i < edges.Length; i++)
{
var nodes = edges[i];
var nodeConnections = connections.GetOrNew(i);
for (var j = i + 1; j < edges.Length; j++)
{
var otherNodes = edges[j];
var intersect = new HashSet<Vector2i>(nodes);
intersect.IntersectWith(otherNodes);
if (intersect.Count == 0)
continue;
nodeConnections[j] = intersect;
var otherNodeConnections = connections.GetOrNew(j);
otherNodeConnections[i] = intersect;
}
}
var tiles = new List<(Vector2i, Tile)>();
var dungeon = new Dungeon();
var availablePacks = new List<DungeonRoomPackPrototype>();
var chosenPacks = new DungeonRoomPackPrototype?[gen.RoomPacks.Count];
var packTransforms = new Matrix3[gen.RoomPacks.Count];
var packRotations = new Angle[gen.RoomPacks.Count];
var rotatedPackNodes = new HashSet<Vector2i>[gen.RoomPacks.Count];
// Actually pick the room packs and rooms
for (var i = 0; i < gen.RoomPacks.Count; i++)
{
var bounds = gen.RoomPacks[i];
var dimensions = new Vector2i(bounds.Width, bounds.Height);
// Try every pack rotation
if (roomPackProtos.TryGetValue(dimensions, out var roomPacks))
{
availablePacks.AddRange(roomPacks);
}
// Try rotated versions if there are any.
if (dimensions.X != dimensions.Y)
{
var rotatedDimensions = new Vector2i(dimensions.Y, dimensions.X);
if (roomPackProtos.TryGetValue(rotatedDimensions, out roomPacks))
{
availablePacks.AddRange(roomPacks);
}
}
// Iterate every pack
// To be valid it needs its edge nodes to overlap with every edge group
var external = connections[i];
random.Shuffle(availablePacks);
Matrix3 packTransform = default!;
var found = false;
DungeonRoomPackPrototype pack = default!;
foreach (var aPack in availablePacks)
{
var aExternal = externalNodes[aPack];
for (var j = 0; j < 4; j++)
{
var dir = (DirectionFlag) Math.Pow(2, j);
Vector2i aPackDimensions;
if ((dir & (DirectionFlag.East | DirectionFlag.West)) != 0x0)
{
aPackDimensions = new Vector2i(aPack.Size.Y, aPack.Size.X);
}
else
{
aPackDimensions = aPack.Size;
}
// Rotation doesn't match.
if (aPackDimensions != bounds.Size)
continue;
found = true;
var rotatedNodes = new HashSet<Vector2i>(aExternal.Count);
var aRotation = dir.AsDir().ToAngle();
// Get the external nodes in terms of the dungeon layout
// (i.e. rotated if necessary + translated to the room position)
foreach (var node in aExternal)
{
// Get the node in pack terms (offset from center), then rotate it
// Afterwards we offset it by where the pack is supposed to be in world terms.
var rotated = aRotation.RotateVec((Vector2) node + grid.TileSize / 2f - aPack.Size / 2f);
rotatedNodes.Add((rotated + bounds.Center).Floored());
}
foreach (var group in external.Values)
{
if (rotatedNodes.Overlaps(group))
continue;
found = false;
break;
}
if (!found)
{
continue;
}
// Use this pack
packTransform = Matrix3.CreateTransform(bounds.Center, aRotation);
packRotations[i] = aRotation;
rotatedPackNodes[i] = rotatedNodes;
pack = aPack;
break;
}
if (found)
break;
}
availablePacks.Clear();
// Oop
if (!found)
{
continue;
}
// If we're not the first pack then connect to our edges.
chosenPacks[i] = pack;
packTransforms[i] = packTransform;
}
// Then for overlaps choose either 1x1 / 3x1
// Pick a random tile for it and then expand outwards as relevant (weighted towards middle?)
for (var i = 0; i < chosenPacks.Length; i++)
{
var pack = chosenPacks[i]!;
var packTransform = packTransforms[i];
var packRotation = packRotations[i];
// Actual spawn cud here.
// Pickout the room pack template to get the room dimensions we need.
// TODO: Need to be able to load entities on top of other entities but das a lot of effo
var packCenter = (Vector2) pack.Size / 2;
foreach (var roomSize in pack.Rooms)
{
var roomDimensions = new Vector2i(roomSize.Width, roomSize.Height);
Angle roomRotation = Angle.Zero;
Matrix3 matty;
if (!roomProtos.TryGetValue(roomDimensions, out var roomProto))
{
roomDimensions = new Vector2i(roomDimensions.Y, roomDimensions.X);
if (!roomProtos.TryGetValue(roomDimensions, out roomProto))
{
Matrix3.Multiply(packTransform, dungeonTransform, out matty);
for (var x = roomSize.Left; x < roomSize.Right; x++)
{
for (var y = roomSize.Bottom; y < roomSize.Top; y++)
{
var index = matty.Transform(new Vector2(x, y) + grid.TileSize / 2f - packCenter).Floored();
tiles.Add((index, new Tile(_tileDefManager["FloorPlanetGrass"].TileId)));
}
}
grid.SetTiles(tiles);
tiles.Clear();
Logger.Error($"Unable to find room variant for {roomDimensions}, leaving empty.");
continue;
}
roomRotation = new Angle(Math.PI / 2);
Logger.Debug($"Using rotated variant for room");
}
if (roomDimensions.X == roomDimensions.Y)
{
// Give it a random rotation
roomRotation = random.Next(4) * Math.PI / 2;
}
else if (random.Next(2) == 1)
{
roomRotation += Math.PI;
}
var roomTransform = Matrix3.CreateTransform(roomSize.Center - packCenter, roomRotation);
var finalRoomRotation = roomRotation + packRotation + dungeonRotation;
Matrix3.Multiply(roomTransform, packTransform, out matty);
Matrix3.Multiply(matty, dungeonTransform, out var dungeonMatty);
var room = roomProto[random.Next(roomProto.Count)];
var roomMap = _dungeon.GetOrCreateTemplate(room);
var templateMapUid = _mapManager.GetMapEntityId(roomMap);
var templateGrid = _entManager.GetComponent<MapGridComponent>(templateMapUid);
var roomCenter = (room.Offset + room.Size / 2f) * grid.TileSize;
var roomTiles = new HashSet<Vector2i>(room.Size.X * room.Size.Y);
// Load tiles
for (var x = 0; x < room.Size.X; x++)
{
for (var y = 0; y < room.Size.Y; y++)
{
var indices = new Vector2i(x + room.Offset.X, y + room.Offset.Y);
var tileRef = templateGrid.GetTileRef(indices);
var tilePos = dungeonMatty.Transform((Vector2) indices + grid.TileSize / 2f - roomCenter);
var rounded = tilePos.Floored();
tiles.Add((rounded, tileRef.Tile));
roomTiles.Add(rounded);
}
}
var center = Vector2.Zero;
foreach (var tile in roomTiles)
{
center += ((Vector2) tile + grid.TileSize / 2f);
}
center /= roomTiles.Count;
dungeon.Rooms.Add(new DungeonRoom(roomTiles, center));
grid.SetTiles(tiles);
tiles.Clear();
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
var metaQuery = _entManager.GetEntityQuery<MetaDataComponent>();
// Load entities
// TODO: I don't think engine supports full entity copying so we do this piece of shit.
var bounds = new Box2(room.Offset, room.Offset + room.Size);
foreach (var templateEnt in _lookup.GetEntitiesIntersecting(templateMapUid, bounds, LookupFlags.Uncontained))
{
var templateXform = xformQuery.GetComponent(templateEnt);
var childPos = dungeonMatty.Transform(templateXform.LocalPosition - roomCenter);
var childRot = templateXform.LocalRotation + finalRoomRotation;
var protoId = metaQuery.GetComponent(templateEnt).EntityPrototype?.ID;
// TODO: Copy the templated entity as is with serv
var ent = _entManager.SpawnEntity(protoId,
new EntityCoordinates(gridUid, childPos));
var childXform = xformQuery.GetComponent(ent);
var anchored = templateXform.Anchored;
_transform.SetLocalRotation(ent, childRot, childXform);
// If the templated entity was anchored then anchor us too.
if (anchored && !childXform.Anchored)
_transform.AnchorEntity(ent, childXform, grid);
else if (!anchored && childXform.Anchored)
_transform.Unanchor(ent, childXform);
}
// Load decals
if (_entManager.TryGetComponent<DecalGridComponent>(templateMapUid, out var loadedDecals))
{
_entManager.EnsureComponent<DecalGridComponent>(gridUid);
foreach (var (_, decal) in _decals.GetDecalsIntersecting(templateMapUid, bounds, loadedDecals))
{
// Offset by 0.5 because decals are offset from bot-left corner
// So we convert it to center of tile then convert it back again after transform.
// Do these shenanigans because 32x32 decals assume as they are centered on bottom-left of tiles.
var position = dungeonMatty.Transform(decal.Coordinates + 0.5f - roomCenter);
position -= 0.5f;
// Umm uhh I love decals so uhhhh idk what to do about this
var angle = (decal.Angle + finalRoomRotation).Reduced();
// Adjust because 32x32 so we can't rotate cleanly
// Yeah idk about the uhh vectors here but it looked visually okay but they may still be off by 1.
// Also EyeManager.PixelsPerMeter should really be in shared.
if (angle.Equals(Math.PI))
{
position += new Vector2(-1f / 32f, 1f / 32f);
}
else if (angle.Equals(Math.PI * 1.5))
{
position += new Vector2(-1f / 32f, 0f);
}
else if (angle.Equals(Math.PI / 2f))
{
position += new Vector2(0f, 1f / 32f);
}
var tilePos = position.Floored();
// Fallback because uhhhhhhhh yeah, a corner tile might look valid on the original
// but place 1 nanometre off grid and fail the add.
if (!grid.TryGetTileRef(tilePos, out var tileRef) || tileRef.Tile.IsEmpty)
{
grid.SetTile(tilePos, fallbackTile);
}
var result = _decals.TryAddDecal(
decal.Id,
new EntityCoordinates(gridUid, position),
out _,
decal.Color,
angle,
decal.ZIndex,
decal.Cleanable);
DebugTools.Assert(result);
}
}
await SuspendIfOutOfTime();
ValidateResume();
}
}
return dungeon;
}
}

View File

@@ -0,0 +1,554 @@
using System.Linq;
using System.Threading.Tasks;
using Content.Server.Light.Components;
using Content.Shared.Physics;
using Content.Shared.Procedural;
using Content.Shared.Procedural.PostGeneration;
using Content.Shared.Storage;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Random;
using Robust.Shared.Utility;
namespace Content.Server.Procedural;
public sealed partial class DungeonJob
{
/*
* Run after the main dungeon generation
*/
private const int CollisionMask = (int) CollisionGroup.Impassable;
private const int CollisionLayer = (int) CollisionGroup.Impassable;
private async Task PostGen(BoundaryWallPostGen gen, Dungeon dungeon, EntityUid gridUid, MapGridComponent grid, Random random)
{
var tile = new Tile(_tileDefManager[gen.Tile].TileId);
var tiles = new List<(Vector2i Index, Tile Tile)>();
// Spawn wall outline
// - Tiles first
foreach (var room in dungeon.Rooms)
{
foreach (var index in room.Tiles)
{
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
var neighbor = new Vector2i(x + index.X, y + index.Y);
if (dungeon.RoomTiles.Contains(neighbor))
continue;
if (!_anchorable.TileFree(grid, neighbor, CollisionLayer, CollisionMask))
continue;
tiles.Add((neighbor, tile));
}
}
}
}
grid.SetTiles(tiles);
// Double iteration coz we bulk set tiles for speed.
for (var i = 0; i < tiles.Count; i++)
{
var index = tiles[i];
if (!_anchorable.TileFree(grid, index.Index, CollisionLayer, CollisionMask))
continue;
// If no cardinal neighbors in dungeon then we're a corner.
var isCorner = false;
if (gen.CornerWall != null)
{
isCorner = true;
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
if (x != 0 && y != 0)
{
continue;
}
var neighbor = new Vector2i(index.Index.X + x, index.Index.Y + y);
if (dungeon.RoomTiles.Contains(neighbor))
{
isCorner = false;
break;
}
}
if (!isCorner)
break;
}
if (isCorner)
_entManager.SpawnEntity(gen.CornerWall, grid.GridTileToLocal(index.Index));
}
if (!isCorner)
_entManager.SpawnEntity(gen.Wall, grid.GridTileToLocal(index.Index));
if (i % 10 == 0)
{
await SuspendIfOutOfTime();
ValidateResume();
}
}
}
private async Task PostGen(EntrancePostGen gen, Dungeon dungeon, EntityUid gridUid, MapGridComponent grid, Random random)
{
var rooms = new List<DungeonRoom>(dungeon.Rooms);
var roomTiles = new List<Vector2i>();
var tileData = new Tile(_tileDefManager[gen.Tile].TileId);
var count = gen.Count;
while (count > 0 && rooms.Count > 0)
{
var roomIndex = random.Next(rooms.Count);
var room = rooms[roomIndex];
rooms.RemoveAt(roomIndex);
// Move out 3 tiles in a direction away from center of the room
// If none of those intersect another tile it's probably external
// TODO: Maybe need to take top half of furthest rooms in case there's interior exits?
roomTiles.AddRange(room.Tiles);
random.Shuffle(roomTiles);
foreach (var tile in roomTiles)
{
// Check the interior node is at least accessible?
// Can't do anchored because it might be a locker or something.
// TODO: Better collision mask check
if (_lookup.GetEntitiesIntersecting(gridUid, tile, LookupFlags.Dynamic | LookupFlags.Static).Any())
continue;
var direction = (tile - room.Center).ToAngle().GetCardinalDir().ToAngle().ToVec();
var isValid = true;
for (var j = 1; j < 4; j++)
{
var neighbor = (tile + direction * j).Floored();
// If it's an interior tile or blocked.
if (dungeon.RoomTiles.Contains(neighbor) || _lookup.GetEntitiesIntersecting(gridUid, neighbor, LookupFlags.Dynamic | LookupFlags.Static).Any())
{
isValid = false;
break;
}
}
if (!isValid)
continue;
var entrancePos = (tile + direction).Floored();
// Entrance wew
grid.SetTile(entrancePos, tileData);
ClearDoor(dungeon, grid, entrancePos);
var gridCoords = grid.GridTileToLocal(entrancePos);
// Need to offset the spawn to avoid spawning in the room.
_entManager.SpawnEntity(gen.Door, gridCoords);
count--;
// Clear out any biome tiles nearby to avoid blocking it
foreach (var nearTile in grid.GetTilesIntersecting(new Circle(gridCoords.Position, 1.5f), false))
{
if (dungeon.RoomTiles.Contains(nearTile.GridIndices))
continue;
grid.SetTile(nearTile.GridIndices, tileData);
}
break;
}
roomTiles.Clear();
}
}
private async Task PostGen(ExternalWindowPostGen gen, Dungeon dungeon, EntityUid gridUid, MapGridComponent grid,
Random random)
{
// Iterate every room with N chance to spawn windows on that wall per cardinal dir.
var chance = 0.25;
var distance = 10;
foreach (var room in dungeon.Rooms)
{
var validTiles = new List<Vector2i>();
for (var i = 0; i < 4; i++)
{
var dir = (DirectionFlag) Math.Pow(2, i);
var dirVec = dir.AsDir().ToIntVec();
foreach (var tile in room.Tiles)
{
var tileAngle = ((Vector2) tile + grid.TileSize / 2f - room.Center).ToAngle();
var roundedAngle = Math.Round(tileAngle.Theta / (Math.PI / 2)) * (Math.PI / 2);
var tileVec = (Vector2i) new Angle(roundedAngle).ToVec().Rounded();
if (!tileVec.Equals(dirVec))
continue;
var valid = true;
for (var j = 1; j < distance; j++)
{
var edgeNeighbor = tile + dirVec * j;
if (dungeon.RoomTiles.Contains(edgeNeighbor))
{
valid = false;
break;
}
}
if (!valid)
continue;
var windowTile = tile + dirVec;
if (!_anchorable.TileFree(grid, windowTile, CollisionLayer, CollisionMask))
continue;
validTiles.Add(windowTile);
}
if (validTiles.Count == 0 || random.NextDouble() > chance)
continue;
validTiles.Sort((x, y) => ((Vector2) x + grid.TileSize / 2f - room.Center).LengthSquared.CompareTo(((Vector2) y + grid.TileSize / 2f - room.Center).LengthSquared));
for (var j = 0; j < Math.Min(validTiles.Count, 3); j++)
{
var tile = validTiles[j];
var gridPos = grid.GridTileToLocal(tile);
grid.SetTile(tile, new Tile(_tileDefManager[gen.Tile].TileId));
foreach (var ent in gen.Entities)
{
_entManager.SpawnEntity(ent, gridPos);
}
}
if (validTiles.Count > 0)
{
await SuspendIfOutOfTime();
ValidateResume();
}
validTiles.Clear();
}
}
}
/*
* You may be wondering why these are different.
* It's because for internals we want to force it as it looks nicer and not leave it up to chance.
*/
// TODO: Can probably combine these a bit, their differences are in really annoying to pull out spots.
private async Task PostGen(InternalWindowPostGen gen, Dungeon dungeon, EntityUid gridUid, MapGridComponent grid,
Random random)
{
// Iterate every room and check if there's a gap beyond it that leads to another room within N tiles
// If so then consider windows
var minDistance = 4;
var maxDistance = 6;
foreach (var room in dungeon.Rooms)
{
var validTiles = new List<Vector2i>();
for (var i = 0; i < 4; i++)
{
var dir = (DirectionFlag) Math.Pow(2, i);
var dirVec = dir.AsDir().ToIntVec();
foreach (var tile in room.Tiles)
{
var tileAngle = ((Vector2) tile + grid.TileSize / 2f - room.Center).ToAngle();
var roundedAngle = Math.Round(tileAngle.Theta / (Math.PI / 2)) * (Math.PI / 2);
var tileVec = (Vector2i) new Angle(roundedAngle).ToVec().Rounded();
if (!tileVec.Equals(dirVec))
continue;
var valid = false;
for (var j = 1; j < maxDistance; j++)
{
var edgeNeighbor = tile + dirVec * j;
if (dungeon.RoomTiles.Contains(edgeNeighbor))
{
if (j < minDistance)
{
valid = false;
}
else
{
valid = true;
}
break;
}
}
if (!valid)
continue;
var windowTile = tile + dirVec;
if (!_anchorable.TileFree(grid, windowTile, CollisionLayer, CollisionMask))
continue;
validTiles.Add(windowTile);
}
validTiles.Sort((x, y) => ((Vector2) x + grid.TileSize / 2f - room.Center).LengthSquared.CompareTo(((Vector2) y + grid.TileSize / 2f - room.Center).LengthSquared));
for (var j = 0; j < Math.Min(validTiles.Count, 3); j++)
{
var tile = validTiles[j];
var gridPos = grid.GridTileToLocal(tile);
grid.SetTile(tile, new Tile(_tileDefManager[gen.Tile].TileId));
foreach (var ent in gen.Entities)
{
_entManager.SpawnEntity(ent, gridPos);
}
}
if (validTiles.Count > 0)
{
await SuspendIfOutOfTime();
ValidateResume();
}
validTiles.Clear();
}
}
}
private async Task PostGen(MiddleConnectionPostGen gen, Dungeon dungeon, EntityUid gridUid, MapGridComponent grid, Random random)
{
// TODO: Need a minimal spanning tree version tbh
// Grab all of the room bounds
// Then, work out connections between them
var roomBorders = new Dictionary<DungeonRoom, HashSet<Vector2i>>(dungeon.Rooms.Count);
foreach (var room in dungeon.Rooms)
{
var roomEdges = new HashSet<Vector2i>();
foreach (var index in room.Tiles)
{
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
// Cardinals only
if (x != 0 && y != 0 ||
x == 0 && y == 0)
{
continue;
}
var neighbor = new Vector2i(index.X + x, index.Y + y);
if (dungeon.RoomTiles.Contains(neighbor))
continue;
if (!_anchorable.TileFree(grid, neighbor, CollisionLayer, CollisionMask))
continue;
roomEdges.Add(neighbor);
}
}
}
roomBorders.Add(room, roomEdges);
}
// Do pathfind from first room to work out graph.
// TODO: Optional loops
var roomConnections = new Dictionary<DungeonRoom, List<DungeonRoom>>();
var frontier = new Queue<DungeonRoom>();
frontier.Enqueue(dungeon.Rooms.First());
var tile = new Tile(_tileDefManager[gen.Tile].TileId);
foreach (var (room, border) in roomBorders)
{
var conns = roomConnections.GetOrNew(room);
foreach (var (otherRoom, otherBorders) in roomBorders)
{
if (room.Equals(otherRoom) ||
conns.Contains(otherRoom))
{
continue;
}
var flipp = new HashSet<Vector2i>(border);
flipp.IntersectWith(otherBorders);
if (flipp.Count == 0 ||
gen.OverlapCount != -1 && flipp.Count != gen.OverlapCount)
continue;
var center = Vector2.Zero;
foreach (var node in flipp)
{
center += (Vector2) node + grid.TileSize / 2f;
}
center /= flipp.Count;
// Weight airlocks towards center more.
var nodeDistances = new List<(Vector2i Node, float Distance)>(flipp.Count);
foreach (var node in flipp)
{
nodeDistances.Add((node, ((Vector2) node + grid.TileSize / 2f - center).LengthSquared));
}
nodeDistances.Sort((x, y) => x.Distance.CompareTo(y.Distance));
var width = gen.Count;
for (var i = 0; i < nodeDistances.Count; i++)
{
var node = nodeDistances[i].Node;
var gridPos = grid.GridTileToLocal(node);
if (!_anchorable.TileFree(grid, node, CollisionLayer, CollisionMask))
continue;
width--;
grid.SetTile(node, tile);
if (gen.EdgeEntities != null && nodeDistances.Count - i <= 2)
{
foreach (var ent in gen.EdgeEntities)
{
_entManager.SpawnEntity(ent, gridPos);
}
}
else
{
// Iterate neighbors and check for blockers, if so bulldoze
ClearDoor(dungeon, grid, node);
foreach (var ent in gen.Entities)
{
_entManager.SpawnEntity(ent, gridPos);
}
}
if (width == 0)
break;
}
conns.Add(otherRoom);
var otherConns = roomConnections.GetOrNew(otherRoom);
otherConns.Add(room);
await SuspendIfOutOfTime();
ValidateResume();
}
}
}
/// <summary>
/// Removes any unwanted obstacles around a door tile.
/// </summary>
private void ClearDoor(Dungeon dungeon, MapGridComponent grid, Vector2i indices, bool strict = false)
{
var flags = strict
? LookupFlags.Dynamic | LookupFlags.Static | LookupFlags.StaticSundries
: LookupFlags.Dynamic | LookupFlags.Static;
var physicsQuery = _entManager.GetEntityQuery<PhysicsComponent>();
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
if (x != 0 && y != 0)
continue;
var neighbor = new Vector2i(indices.X + x, indices.Y + y);
if (!dungeon.RoomTiles.Contains(neighbor))
continue;
foreach (var ent in _lookup.GetEntitiesIntersecting(_gridUid, neighbor, flags))
{
if (!physicsQuery.TryGetComponent(ent, out var physics) ||
(CollisionMask & physics.CollisionLayer) == 0x0 &&
(CollisionLayer & physics.CollisionMask) == 0x0)
{
continue;
}
_entManager.DeleteEntity(ent);
}
}
}
}
private async Task PostGen(WallMountPostGen gen, Dungeon dungeon, EntityUid gridUid, MapGridComponent grid,
Random random)
{
var tileDef = new Tile(_tileDefManager[gen.Tile].TileId);
var checkedTiles = new HashSet<Vector2i>();
foreach (var room in dungeon.Rooms)
{
foreach (var tile in room.Tiles)
{
for (var x = -1; x <= 1; x++)
{
for (var y = -1; y <= 1; y++)
{
if (x != 0 && y != 0)
{
continue;
}
var neighbor = new Vector2i(tile.X + x, tile.Y + y);
// Occupado
if (dungeon.RoomTiles.Contains(neighbor) || checkedTiles.Contains(neighbor) || !_anchorable.TileFree(grid, neighbor, CollisionLayer, CollisionMask))
continue;
if (!random.Prob(gen.Prob) || !checkedTiles.Add(neighbor))
continue;
grid.SetTile(neighbor, tileDef);
var gridPos = grid.GridTileToLocal(neighbor);
foreach (var ent in EntitySpawnCollection.GetSpawns(gen.Spawns, random))
{
_entManager.SpawnEntity(ent, gridPos);
}
}
}
}
}
}
}

View File

@@ -0,0 +1,139 @@
using System.Threading;
using System.Threading.Tasks;
using Content.Server.Construction;
using Content.Server.CPUJob.JobQueues;
using Content.Server.Decals;
using Content.Shared.Procedural;
using Content.Shared.Procedural.DungeonGenerators;
using Content.Shared.Procedural.PostGeneration;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
namespace Content.Server.Procedural;
public sealed partial class DungeonJob : Job<Dungeon>
{
private readonly IEntityManager _entManager;
private readonly IMapManager _mapManager;
private readonly IPrototypeManager _prototype;
private readonly ITileDefinitionManager _tileDefManager;
private readonly AnchorableSystem _anchorable;
private readonly DecalSystem _decals;
private readonly DungeonSystem _dungeon;
private readonly EntityLookupSystem _lookup;
private readonly SharedTransformSystem _transform;
private readonly DungeonConfigPrototype _gen;
private readonly int _seed;
private readonly Vector2 _position;
private readonly MapGridComponent _grid;
private readonly EntityUid _gridUid;
private readonly ISawmill _sawmill;
public DungeonJob(
ISawmill sawmill,
double maxTime,
IEntityManager entManager,
IMapManager mapManager,
IPrototypeManager prototype,
ITileDefinitionManager tileDefManager,
AnchorableSystem anchorable,
DecalSystem decals,
DungeonSystem dungeon,
EntityLookupSystem lookup,
SharedTransformSystem transform,
DungeonConfigPrototype gen,
MapGridComponent grid,
EntityUid gridUid,
int seed,
Vector2 position,
CancellationToken cancellation = default) : base(maxTime, cancellation)
{
_sawmill = sawmill;
_entManager = entManager;
_mapManager = mapManager;
_prototype = prototype;
_tileDefManager = tileDefManager;
_anchorable = anchorable;
_decals = decals;
_dungeon = dungeon;
_lookup = lookup;
_transform = transform;
_gen = gen;
_grid = grid;
_gridUid = gridUid;
_seed = seed;
_position = position;
}
protected override async Task<Dungeon?> Process()
{
Dungeon dungeon;
_sawmill.Info($"Generating dungeon {_gen.ID} with seed {_seed} on {_entManager.ToPrettyString(_gridUid)}");
switch (_gen.Generator)
{
case PrefabDunGen prefab:
dungeon = await GeneratePrefabDungeon(prefab, _gridUid, _grid, _seed);
break;
default:
throw new NotImplementedException();
}
foreach (var room in dungeon.Rooms)
{
dungeon.RoomTiles.UnionWith(room.Tiles);
}
// To make it slightly more deterministic treat this RNG as separate ig.
var random = new Random(_seed);
foreach (var post in _gen.PostGeneration)
{
_sawmill.Debug($"Doing postgen {post.GetType()} for {_gen.ID} with seed {_seed}");
switch (post)
{
case MiddleConnectionPostGen dordor:
await PostGen(dordor, dungeon, _gridUid, _grid, random);
break;
case EntrancePostGen entrance:
await PostGen(entrance, dungeon, _gridUid, _grid, random);
break;
case ExternalWindowPostGen externalWindow:
await PostGen(externalWindow, dungeon, _gridUid, _grid, random);
break;
case InternalWindowPostGen internalWindow:
await PostGen(internalWindow, dungeon, _gridUid, _grid, random);
break;
case BoundaryWallPostGen boundary:
await PostGen(boundary, dungeon, _gridUid, _grid, random);
break;
case WallMountPostGen wall:
await PostGen(wall, dungeon, _gridUid, _grid, random);
break;
default:
throw new NotImplementedException();
}
await SuspendIfOutOfTime();
ValidateResume();
}
return dungeon;
}
private bool ValidateResume()
{
if (_entManager.Deleted(_gridUid))
return false;
return true;
}
}

View File

@@ -0,0 +1,102 @@
using System.Threading.Tasks;
using Content.Server.Administration;
using Content.Shared.Administration;
using Content.Shared.Procedural;
using Content.Shared.Procedural.DungeonGenerators;
using Robust.Shared.Console;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
namespace Content.Server.Procedural;
public sealed partial class DungeonSystem
{
/// <summary>
/// Generates a dungeon via command.
/// </summary>
[AdminCommand(AdminFlags.Fun)]
private async void GenerateDungeon(IConsoleShell shell, string argstr, string[] args)
{
if (args.Length < 4)
{
shell.WriteError("cmd-dungen-arg-count");
return;
}
if (!int.TryParse(args[0], out var mapInt))
{
shell.WriteError("cmd-dungen-map-parse");
return;
}
var mapId = new MapId(mapInt);
var mapUid = _mapManager.GetMapEntityId(mapId);
if (!TryComp<MapGridComponent>(mapUid, out var mapGrid))
{
shell.WriteError(Loc.GetString("cmd-dungen-mapgrid"));
return;
}
if (!_prototype.TryIndex<DungeonConfigPrototype>(args[1], out var dungeon))
{
shell.WriteError(Loc.GetString("cmd-dungen-config"));
return;
}
if (!int.TryParse(args[2], out var posX) || !int.TryParse(args[3], out var posY))
{
shell.WriteError(Loc.GetString("cmd-dungen-pos"));
return;
}
var position = new Vector2(posX, posY);
int seed;
if (args.Length >= 5)
{
if (!int.TryParse(args[4], out seed))
{
shell.WriteError(Loc.GetString("cmd-dungen-seed"));
return;
}
}
else
{
seed = new Random().Next();
}
shell.WriteLine(Loc.GetString("cmd-dungen-start", ("seed", seed)));
GenerateDungeon(dungeon, mapUid, mapGrid, position, seed);
}
private CompletionResult CompletionCallback(IConsoleShell shell, string[] args)
{
if (args.Length == 1)
{
return CompletionResult.FromHintOptions(CompletionHelper.MapIds(EntityManager), Loc.GetString("cmd-dungen-hint-map"));
}
if (args.Length == 2)
{
return CompletionResult.FromHintOptions(CompletionHelper.PrototypeIDs<DungeonConfigPrototype>(proto: _prototype), Loc.GetString("cmd-dungen-hint-config"));
}
if (args.Length == 3)
{
return CompletionResult.FromHint(Loc.GetString("cmd-dungen-hint-posx"));
}
if (args.Length == 4)
{
return CompletionResult.FromHint(Loc.GetString("cmd-dungen-hint-posy"));
}
if (args.Length == 5)
{
return CompletionResult.FromHint(Loc.GetString("cmd-dungen-hint-seed"));
}
return CompletionResult.Empty;
}
}

View File

@@ -0,0 +1,236 @@
using System.Threading;
using System.Threading.Tasks;
using Content.Server.Construction;
using Content.Server.CPUJob.JobQueues.Queues;
using Content.Server.Decals;
using Content.Server.GameTicking.Events;
using Content.Shared.CCVar;
using Content.Shared.Procedural;
using Robust.Server.GameObjects;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
namespace Content.Server.Procedural;
public sealed partial class DungeonSystem : EntitySystem
{
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IConsoleHost _console = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
[Dependency] private readonly AnchorableSystem _anchorable = default!;
[Dependency] private readonly DecalSystem _decals = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly MapLoaderSystem _loader = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
private ISawmill _sawmill = default!;
private const double DungeonJobTime = 0.005;
private readonly JobQueue _dungeonJobQueue = new(DungeonJobTime);
private readonly Dictionary<DungeonJob, CancellationTokenSource> _dungeonJobs = new();
public override void Initialize()
{
base.Initialize();
_sawmill = Logger.GetSawmill("dungen");
_console.RegisterCommand("dungen", Loc.GetString("cmd-dungen-desc"), Loc.GetString("cmd-dungen-help"), GenerateDungeon, CompletionCallback);
_prototype.PrototypesReloaded += PrototypeReload;
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
}
public override void Update(float frameTime)
{
base.Update(frameTime);
_dungeonJobQueue.Process();
}
private void OnRoundStart(RoundStartingEvent ev)
{
foreach (var token in _dungeonJobs.Values)
{
token.Cancel();
}
_dungeonJobs.Clear();
var query = AllEntityQuery<DungeonAtlasTemplateComponent>();
while (query.MoveNext(out var uid, out _))
{
QueueDel(uid);
}
if (!_configManager.GetCVar(CCVars.ProcgenPreload))
return;
// Force all templates to be setup.
foreach (var room in _prototype.EnumeratePrototypes<DungeonRoomPrototype>())
{
GetOrCreateTemplate(room);
}
}
public override void Shutdown()
{
base.Shutdown();
_prototype.PrototypesReloaded -= PrototypeReload;
foreach (var token in _dungeonJobs.Values)
{
token.Cancel();
}
_dungeonJobs.Clear();
}
private void PrototypeReload(PrototypesReloadedEventArgs obj)
{
if (!obj.ByType.TryGetValue(typeof(DungeonRoomPrototype), out var rooms))
{
return;
}
foreach (var proto in rooms.Modified.Values)
{
var roomProto = (DungeonRoomPrototype) proto;
var query = AllEntityQuery<DungeonAtlasTemplateComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (!roomProto.AtlasPath.Equals(comp.Path))
continue;
QueueDel(uid);
break;
}
}
if (!_configManager.GetCVar(CCVars.ProcgenPreload))
return;
foreach (var proto in rooms.Modified.Values)
{
var roomProto = (DungeonRoomPrototype) proto;
var query = AllEntityQuery<DungeonAtlasTemplateComponent>();
var found = false;
while (query.MoveNext(out var comp))
{
if (!roomProto.AtlasPath.Equals(comp.Path))
continue;
found = true;
break;
}
if (!found)
{
GetOrCreateTemplate(roomProto);
}
}
}
public MapId GetOrCreateTemplate(DungeonRoomPrototype proto)
{
var query = AllEntityQuery<DungeonAtlasTemplateComponent>();
DungeonAtlasTemplateComponent? comp;
while (query.MoveNext(out var uid, out comp))
{
// Exists
if (comp.Path?.Equals(proto.AtlasPath) == true)
return Transform(uid).MapID;
}
var mapId = _mapManager.CreateMap();
_loader.Load(mapId, proto.AtlasPath.ToString());
var mapUid = _mapManager.GetMapEntityId(mapId);
_mapManager.SetMapPaused(mapId, true);
comp = AddComp<DungeonAtlasTemplateComponent>(mapUid);
comp.Path = proto.AtlasPath;
return mapId;
}
public void GenerateDungeon(DungeonConfigPrototype gen,
EntityUid gridUid,
MapGridComponent grid,
Vector2 position,
int seed)
{
var cancelToken = new CancellationTokenSource();
var job = new DungeonJob(
_sawmill,
DungeonJobTime,
EntityManager,
_mapManager,
_prototype,
_tileDefManager,
_anchorable,
_decals,
this,
_lookup,
_transform,
gen,
grid,
gridUid,
seed,
position,
cancelToken.Token);
_dungeonJobs.Add(job, cancelToken);
_dungeonJobQueue.EnqueueJob(job);
job.Run();
}
public async Task<Dungeon> GenerateDungeonAsync(
DungeonConfigPrototype gen,
EntityUid gridUid,
MapGridComponent grid,
Vector2 position,
int seed)
{
var cancelToken = new CancellationTokenSource();
var job = new DungeonJob(
_sawmill,
DungeonJobTime,
EntityManager,
_mapManager,
_prototype,
_tileDefManager,
_anchorable,
_decals,
this,
_lookup,
_transform,
gen,
grid,
gridUid,
seed,
position,
cancelToken.Token);
_dungeonJobs.Add(job, cancelToken);
_dungeonJobQueue.EnqueueJob(job);
job.Run();
await job.AsTask;
if (job.Exception != null)
{
throw job.Exception;
}
return job.Result!;
}
public Angle GetDungeonRotation(int seed)
{
// Mask 0 | 1 for rotation seed
var dungeonRotationSeed = 3 & seed;
return Math.PI / 2 * dungeonRotationSeed;
}
}

View File

@@ -11,7 +11,7 @@ namespace Content.Server.Salvage
public string ID { get; } = default!; public string ID { get; } = default!;
/// <summary> /// <summary>
/// Relative directory path to the given map, i.e. `Maps/Salvage/test.yml` /// Relative directory path to the given map, i.e. `Maps/Salvage/template.yml`
/// </summary> /// </summary>
[DataField("mapPath", required: true)] [DataField("mapPath", required: true)]
public ResourcePath MapPath { get; } = default!; public ResourcePath MapPath { get; } = default!;

View File

@@ -16,29 +16,45 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Random; using Robust.Shared.Random;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using System.Linq; using System.Linq;
using Content.Server.Cargo.Systems;
using Content.Server.NPC.Pathfinding;
using Content.Server.Parallax;
using Content.Server.Procedural;
using Content.Server.Station.Systems;
using Robust.Shared.Timing;
namespace Content.Server.Salvage namespace Content.Server.Salvage
{ {
public sealed class SalvageSystem : EntitySystem public sealed partial class SalvageSystem : SharedSalvageSystem
{ {
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly BiomeSystem _biome = default!;
[Dependency] private readonly CargoSystem _cargo = default!;
[Dependency] private readonly DungeonSystem _dungeon = default!;
[Dependency] private readonly MapLoaderSystem _map = default!; [Dependency] private readonly MapLoaderSystem _map = default!;
[Dependency] private readonly PathfindingSystem _pathfinding = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly RadioSystem _radioSystem = default!; [Dependency] private readonly RadioSystem _radioSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
private static readonly int SalvageLocationPlaceAttempts = 16; private static readonly int SalvageLocationPlaceAttempts = 16;
// TODO: This is probably not compatible with multi-station // TODO: This is probably not compatible with multi-station
private readonly Dictionary<EntityUid, SalvageGridState> _salvageGridStates = new(); private readonly Dictionary<EntityUid, SalvageGridState> _salvageGridStates = new();
private ISawmill _sawmill = default!;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
_sawmill = Logger.GetSawmill("salvage");
SubscribeLocalEvent<SalvageMagnetComponent, InteractHandEvent>(OnInteractHand); SubscribeLocalEvent<SalvageMagnetComponent, InteractHandEvent>(OnInteractHand);
SubscribeLocalEvent<SalvageMagnetComponent, ExaminedEvent>(OnExamined); SubscribeLocalEvent<SalvageMagnetComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<SalvageMagnetComponent, ComponentShutdown>(OnMagnetRemoval); SubscribeLocalEvent<SalvageMagnetComponent, ComponentShutdown>(OnMagnetRemoval);

View File

@@ -5,4 +5,5 @@ namespace Content.Server.Shuttles.Events;
/// <summary> /// <summary>
/// Raised when <see cref="ShuttleSystem.FasterThanLight"/> has completed FTL Travel. /// Raised when <see cref="ShuttleSystem.FasterThanLight"/> has completed FTL Travel.
/// </summary> /// </summary>
public sealed class HyperspaceJumpCompletedEvent: EntityEventArgs {} [ByRefEvent]
public readonly record struct FTLCompletedEvent;

View File

@@ -46,6 +46,19 @@ namespace Content.Server.Shuttles.Systems
SubscribeLocalEvent<PilotComponent, MoveEvent>(HandlePilotMove); SubscribeLocalEvent<PilotComponent, MoveEvent>(HandlePilotMove);
SubscribeLocalEvent<PilotComponent, ComponentGetState>(OnGetState); SubscribeLocalEvent<PilotComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<FTLDestinationComponent, ComponentStartup>(OnFtlDestStartup);
SubscribeLocalEvent<FTLDestinationComponent, ComponentShutdown>(OnFtlDestShutdown);
}
private void OnFtlDestStartup(EntityUid uid, FTLDestinationComponent component, ComponentStartup args)
{
RefreshShuttleConsoles();
}
private void OnFtlDestShutdown(EntityUid uid, FTLDestinationComponent component, ComponentShutdown args)
{
RefreshShuttleConsoles();
} }
private void OnDestinationMessage(EntityUid uid, ShuttleConsoleComponent component, ShuttleConsoleDestinationMessage args) private void OnDestinationMessage(EntityUid uid, ShuttleConsoleComponent component, ShuttleConsoleDestinationMessage args)
@@ -81,7 +94,7 @@ namespace Content.Server.Shuttles.Systems
return; return;
} }
_shuttle.FTLTravel(shuttle, args.Destination, hyperspaceTime: _shuttle.TransitTime); _shuttle.FTLTravel(shuttle, args.Destination);
} }
private void OnDock(DockEvent ev) private void OnDock(DockEvent ev)
@@ -259,7 +272,6 @@ namespace Content.Server.Shuttles.Systems
var canTravel = !locked && var canTravel = !locked &&
comp.Enabled && comp.Enabled &&
!Paused(comp.Owner, meta) &&
(!TryComp<FTLComponent>(comp.Owner, out var ftl) || ftl.State == FTLState.Cooldown); (!TryComp<FTLComponent>(comp.Owner, out var ftl) || ftl.State == FTLState.Cooldown);
// Can't travel to same map. // Can't travel to same map.

View File

@@ -16,6 +16,7 @@ using Content.Server.Shuttles.Events;
using Content.Shared.Buckle.Components; using Content.Shared.Buckle.Components;
using Content.Shared.Doors.Components; using Content.Shared.Doors.Components;
using Robust.Shared.Map.Components; using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Components;
namespace Content.Server.Shuttles.Systems; namespace Content.Server.Shuttles.Systems;
@@ -71,12 +72,6 @@ public sealed partial class ShuttleSystem
private void InitializeFTL() private void InitializeFTL()
{ {
SubscribeLocalEvent<StationGridAddedEvent>(OnStationGridAdd); SubscribeLocalEvent<StationGridAddedEvent>(OnStationGridAdd);
SubscribeLocalEvent<FTLDestinationComponent, EntityPausedEvent>(OnDestinationPause);
}
private void OnDestinationPause(EntityUid uid, FTLDestinationComponent component, ref EntityPausedEvent args)
{
_console.RefreshShuttleConsoles();
} }
private void OnStationGridAdd(StationGridAddedEvent ev) private void OnStationGridAdd(StationGridAddedEvent ev)
@@ -216,7 +211,8 @@ public sealed partial class ShuttleSystem
if (comp.Accumulator > 0f) continue; if (comp.Accumulator > 0f) continue;
var xform = Transform(comp.Owner); var uid = comp.Owner;
var xform = Transform(uid);
PhysicsComponent? body; PhysicsComponent? body;
ShuttleComponent? shuttle; ShuttleComponent? shuttle;
@@ -228,16 +224,17 @@ public sealed partial class ShuttleSystem
comp.State = FTLState.Travelling; comp.State = FTLState.Travelling;
var width = Comp<MapGridComponent>(comp.Owner).LocalAABB.Width; var width = Comp<MapGridComponent>(uid).LocalAABB.Width;
xform.Coordinates = new EntityCoordinates(_mapManager.GetMapEntityId(_hyperSpaceMap!.Value), new Vector2(_index + width / 2f, 0f)); xform.Coordinates = new EntityCoordinates(_mapManager.GetMapEntityId(_hyperSpaceMap!.Value), new Vector2(_index + width / 2f, 0f));
xform.LocalRotation = Angle.Zero; xform.LocalRotation = Angle.Zero;
_index += width + Buffer; _index += width + Buffer;
comp.Accumulator += comp.TravelTime - DefaultArrivalTime; comp.Accumulator += comp.TravelTime - DefaultArrivalTime;
if (TryComp(comp.Owner, out body)) if (TryComp(uid, out body))
{ {
_physics.SetLinearVelocity(comp.Owner, new Vector2(0f, 20f), body: body); Enable(uid, body);
_physics.SetAngularVelocity(comp.Owner, 0f, body: body); _physics.SetLinearVelocity(uid, new Vector2(0f, 20f), body: body);
_physics.SetAngularVelocity(uid, 0f, body: body);
_physics.SetLinearDamping(body, 0f); _physics.SetLinearDamping(body, 0f);
_physics.SetAngularDamping(body, 0f); _physics.SetAngularDamping(body, 0f);
} }
@@ -245,11 +242,11 @@ public sealed partial class ShuttleSystem
if (comp.TravelSound != null) if (comp.TravelSound != null)
{ {
comp.TravelStream = SoundSystem.Play(comp.TravelSound.GetSound(), comp.TravelStream = SoundSystem.Play(comp.TravelSound.GetSound(),
Filter.Pvs(comp.Owner, 4f, entityManager: EntityManager), comp.TravelSound.Params); Filter.Pvs(uid, 4f, entityManager: EntityManager), comp.TravelSound.Params);
} }
SetDockBolts(comp.Owner, true); SetDockBolts(uid, true);
_console.RefreshShuttleConsoles(comp.Owner); _console.RefreshShuttleConsoles(uid);
break; break;
// Arriving, play effects // Arriving, play effects
case FTLState.Travelling: case FTLState.Travelling:
@@ -258,29 +255,22 @@ public sealed partial class ShuttleSystem
// TODO: Arrival effects // TODO: Arrival effects
// For now we'll just use the ss13 bubbles but we can do fancier. // For now we'll just use the ss13 bubbles but we can do fancier.
if (TryComp(comp.Owner, out shuttle)) if (TryComp(uid, out shuttle))
{ {
_thruster.DisableLinearThrusters(shuttle); _thruster.DisableLinearThrusters(shuttle);
_thruster.EnableLinearThrustDirection(shuttle, DirectionFlag.South); _thruster.EnableLinearThrustDirection(shuttle, DirectionFlag.South);
} }
_console.RefreshShuttleConsoles(comp.Owner); _console.RefreshShuttleConsoles(uid);
break; break;
// Arrived // Arrived
case FTLState.Arriving: case FTLState.Arriving:
DoTheDinosaur(xform); DoTheDinosaur(xform);
SetDockBolts(comp.Owner, false); SetDockBolts(uid, false);
SetDocks(comp.Owner, true); SetDocks(uid, true);
if (TryComp(comp.Owner, out body)) TryComp(uid, out shuttle);
{ MapId mapId;
_physics.SetLinearVelocity(comp.Owner, Vector2.Zero, body: body);
_physics.SetAngularVelocity(comp.Owner, 0f, body: body);
_physics.SetLinearDamping(body, ShuttleLinearDamping);
_physics.SetAngularDamping(body, ShuttleAngularDamping);
}
TryComp(comp.Owner, out shuttle);
if (comp.TargetUid != null && shuttle != null) if (comp.TargetUid != null && shuttle != null)
{ {
@@ -288,10 +278,30 @@ public sealed partial class ShuttleSystem
TryFTLDock(shuttle, comp.TargetUid.Value); TryFTLDock(shuttle, comp.TargetUid.Value);
else else
TryFTLProximity(shuttle, comp.TargetUid.Value); TryFTLProximity(shuttle, comp.TargetUid.Value);
mapId = Transform(comp.TargetUid.Value).MapID;
} }
else else
{ {
xform.Coordinates = comp.TargetCoordinates; xform.Coordinates = comp.TargetCoordinates;
mapId = comp.TargetCoordinates.GetMapId(EntityManager);
}
if (TryComp(uid, out body))
{
_physics.SetLinearVelocity(uid, Vector2.Zero, body: body);
_physics.SetAngularVelocity(uid, 0f, body: body);
// Disable shuttle if it's on a planet; unfortunately can't do this in parent change messages due
// to event ordering and awake body shenanigans (at least for now).
if (HasComp<MapGridComponent>(xform.MapUid))
{
Disable(uid, body);
}
else
{
Enable(uid, body);
}
} }
if (shuttle != null) if (shuttle != null)
@@ -305,25 +315,28 @@ public sealed partial class ShuttleSystem
comp.TravelStream = null; comp.TravelStream = null;
} }
SoundSystem.Play(_arrivalSound.GetSound(), Filter.Empty().AddInRange(Transform(comp.Owner).MapPosition, GetSoundRange(comp.Owner)), _arrivalSound.Params); SoundSystem.Play(_arrivalSound.GetSound(), Filter.Empty().AddInRange(Transform(uid).MapPosition, GetSoundRange(uid)), _arrivalSound.Params);
if (TryComp<FTLDestinationComponent>(comp.Owner, out var dest)) if (TryComp<FTLDestinationComponent>(uid, out var dest))
{ {
dest.Enabled = true; dest.Enabled = true;
} }
comp.State = FTLState.Cooldown; comp.State = FTLState.Cooldown;
comp.Accumulator += FTLCooldown; comp.Accumulator += FTLCooldown;
_console.RefreshShuttleConsoles(comp.Owner); _console.RefreshShuttleConsoles(uid);
RaiseLocalEvent(new HyperspaceJumpCompletedEvent()); var mapUid = _mapManager.GetMapEntityId(mapId);
_mapManager.SetMapPaused(mapId, false);
var ftlEvent = new FTLCompletedEvent();
RaiseLocalEvent(mapUid, ref ftlEvent, true);
break; break;
case FTLState.Cooldown: case FTLState.Cooldown:
RemComp<FTLComponent>(comp.Owner); RemComp<FTLComponent>(uid);
_console.RefreshShuttleConsoles(comp.Owner); _console.RefreshShuttleConsoles(uid);
break; break;
default: default:
_sawmill.Error($"Found invalid FTL state {comp.State} for {comp.Owner}"); _sawmill.Error($"Found invalid FTL state {comp.State} for {uid}");
RemComp<FTLComponent>(comp.Owner); RemComp<FTLComponent>(uid);
break; break;
} }
} }
@@ -452,6 +465,7 @@ public sealed partial class ShuttleSystem
public bool TryFTLProximity(ShuttleComponent component, EntityUid targetUid, TransformComponent? xform = null, TransformComponent? targetXform = null) public bool TryFTLProximity(ShuttleComponent component, EntityUid targetUid, TransformComponent? xform = null, TransformComponent? targetXform = null)
{ {
if (!Resolve(targetUid, ref targetXform) || if (!Resolve(targetUid, ref targetXform) ||
targetXform.GridUid == null ||
targetXform.MapUid == null || targetXform.MapUid == null ||
!targetXform.MapUid.Value.IsValid() || !targetXform.MapUid.Value.IsValid() ||
!Resolve(component.Owner, ref xform)) !Resolve(component.Owner, ref xform))
@@ -466,7 +480,7 @@ public sealed partial class ShuttleSystem
// Spawn nearby. // Spawn nearby.
// We essentially expand the Box2 of the target area until nothing else is added then we know it's valid. // We essentially expand the Box2 of the target area until nothing else is added then we know it's valid.
// Can't just get an AABB of every grid as we may spawn very far away. // Can't just get an AABB of every grid as we may spawn very far away.
if (TryComp<MapGridComponent>(targetUid, out var targetGrid)) if (TryComp<MapGridComponent>(targetXform.GridUid, out var targetGrid))
{ {
targetLocalAABB = targetGrid.LocalAABB; targetLocalAABB = targetGrid.LocalAABB;
} }
@@ -477,7 +491,7 @@ public sealed partial class ShuttleSystem
var targetAABB = _transform.GetWorldMatrix(targetXform, xformQuery) var targetAABB = _transform.GetWorldMatrix(targetXform, xformQuery)
.TransformBox(targetLocalAABB).Enlarged(shuttleAABB.Size.Length); .TransformBox(targetLocalAABB).Enlarged(shuttleAABB.Size.Length);
var nearbyGrids = new HashSet<EntityUid>(1) { targetUid }; var nearbyGrids = new HashSet<EntityUid>(1) { targetXform.GridUid.Value };
var iteration = 0; var iteration = 0;
var lastCount = 1; var lastCount = 1;
var mapId = targetXform.MapID; var mapId = targetXform.MapID;
@@ -518,8 +532,7 @@ public sealed partial class ShuttleSystem
break; break;
} }
var minRadius = (MathF.Max(targetAABB.Width, targetAABB.Height) + MathF.Max(shuttleAABB.Width, shuttleAABB.Height)) / 2f; Vector2 spawnPos;
var spawnPos = targetAABB.Center + _random.NextVector2(minRadius, minRadius + 64f);
if (TryComp<PhysicsComponent>(component.Owner, out var shuttleBody)) if (TryComp<PhysicsComponent>(component.Owner, out var shuttleBody))
{ {
@@ -527,8 +540,34 @@ public sealed partial class ShuttleSystem
_physics.SetAngularVelocity(component.Owner, 0f, body: shuttleBody); _physics.SetAngularVelocity(component.Owner, 0f, body: shuttleBody);
} }
// TODO: This is pretty crude for multiple landings.
if (nearbyGrids.Count > 1 || !HasComp<MapComponent>(targetXform.GridUid.Value))
{
var minRadius = (MathF.Max(targetAABB.Width, targetAABB.Height) + MathF.Max(shuttleAABB.Width, shuttleAABB.Height)) / 2f;
spawnPos = targetAABB.Center + _random.NextVector2(minRadius, minRadius + 64f);
}
else if (shuttleBody != null)
{
var (targetPos, targetRot) = _transform.GetWorldPositionRotation(targetXform, xformQuery);
var transform = new Transform(targetPos, targetRot);
spawnPos = Robust.Shared.Physics.Transform.Mul(transform, -shuttleBody.LocalCenter);
}
else
{
spawnPos = _transform.GetWorldPosition(targetXform, xformQuery);
}
xform.Coordinates = new EntityCoordinates(targetXform.MapUid.Value, spawnPos); xform.Coordinates = new EntityCoordinates(targetXform.MapUid.Value, spawnPos);
xform.WorldRotation = _random.NextAngle();
if (!HasComp<MapComponent>(targetXform.GridUid.Value))
{
_transform.SetLocalRotation(xform, _random.NextAngle());
}
else
{
_transform.SetLocalRotation(xform, Angle.Zero);
}
return true; return true;
} }
} }

View File

@@ -1031,6 +1031,16 @@ namespace Content.Shared.CCVar
public static readonly CVarDef<bool> BanHardwareIds = public static readonly CVarDef<bool> BanHardwareIds =
CVarDef.Create("ban.hardware_ids", true, CVar.SERVERONLY); CVarDef.Create("ban.hardware_ids", true, CVar.SERVERONLY);
/*
* Procgen
*/
/// <summary>
/// Should we pre-load all of the procgen atlasses.
/// </summary>
public static readonly CVarDef<bool> ProcgenPreload =
CVarDef.Create("procgen.preload", true, CVar.SERVERONLY);
/* /*
* Shuttles * Shuttles
*/ */

View File

@@ -36,7 +36,6 @@ namespace Content.Shared.Movement.Systems
[Dependency] protected readonly IGameTiming Timing = default!; [Dependency] protected readonly IGameTiming Timing = default!;
[Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
[Dependency] private readonly SharedBiomeSystem _biome = default!;
[Dependency] private readonly InventorySystem _inventory = default!; [Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly EntityLookupSystem _lookup = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!;

View File

@@ -1,4 +1,5 @@
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Noise;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Parallax.Biomes; namespace Content.Shared.Parallax.Biomes;
@@ -6,6 +7,8 @@ namespace Content.Shared.Parallax.Biomes;
[RegisterComponent, NetworkedComponent] [RegisterComponent, NetworkedComponent]
public sealed class BiomeComponent : Component public sealed class BiomeComponent : Component
{ {
public FastNoiseLite Noise = new();
[ViewVariables(VVAccess.ReadWrite), DataField("seed")] [ViewVariables(VVAccess.ReadWrite), DataField("seed")]
public int Seed; public int Seed;
@@ -36,4 +39,10 @@ public sealed class BiomeComponent : Component
/// </summary> /// </summary>
[DataField("loadedChunks")] [DataField("loadedChunks")]
public readonly HashSet<Vector2i> LoadedChunks = new(); public readonly HashSet<Vector2i> LoadedChunks = new();
/// <summary>
/// Are we currently in the process of generating?
/// Used to flag modified tiles without callers having to deal with it.
/// </summary>
public bool Generating = false;
} }

View File

@@ -4,7 +4,6 @@ using Robust.Shared.Noise;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Robust.Shared.Utility;
namespace Content.Shared.Parallax.Biomes; namespace Content.Shared.Parallax.Biomes;
@@ -13,6 +12,9 @@ public sealed class BiomePrototype : IPrototype
{ {
[IdDataField] public string ID { get; } = default!; [IdDataField] public string ID { get; } = default!;
[DataField("desc")]
public string Description = string.Empty;
[DataField("layers")] [DataField("layers")]
public List<IBiomeLayer> Layers = new(); public List<IBiomeLayer> Layers = new();
} }
@@ -20,37 +22,25 @@ public sealed class BiomePrototype : IPrototype
[ImplicitDataDefinitionForInheritors] [ImplicitDataDefinitionForInheritors]
public interface IBiomeLayer public interface IBiomeLayer
{ {
/// <summary>
/// Seed is used an offset from the relevant BiomeComponent's seed.
/// </summary>
FastNoiseLite Noise { get; }
/// <summary> /// <summary>
/// Threshold for this layer to be present. If set to 0 forces it for every tile. /// Threshold for this layer to be present. If set to 0 forces it for every tile.
/// </summary> /// </summary>
float Threshold { get; } float Threshold { get; }
/// <summary>
/// Offset the seed by the specified amount for this layer.
/// Useful if you have 2 similar layers but don't want them to match exactly.
/// </summary>
int SeedOffset { get; }
/// <summary>
/// Frequency for noise: lower values create larger blobs.
/// </summary>
float Frequency { get; }
} }
public sealed class BiomeTileLayer : IBiomeLayer public sealed class BiomeTileLayer : IBiomeLayer
{ {
[DataField("noise")] public FastNoiseLite Noise { get; } = new(0);
/// <inheritdoc/> /// <inheritdoc/>
[DataField("threshold")] [DataField("threshold")]
public float Threshold { get; } = 0.5f; public float Threshold { get; } = 0.5f;
/// <inheritdoc/>
[DataField("seedOffset")]
public int SeedOffset { get; } = 0;
/// <inheritdoc/>
[DataField("frequency")]
public float Frequency { get; } = 0.1f;
/// <summary> /// <summary>
/// Which tile variants to use for this layer. Uses all of the tile's variants if none specified /// Which tile variants to use for this layer. Uses all of the tile's variants if none specified
/// </summary> /// </summary>
@@ -84,13 +74,8 @@ public sealed class BiomeDecalLayer : IBiomeWorldLayer
[DataField("divisions")] [DataField("divisions")]
public float Divisions = 1f; public float Divisions = 1f;
/// <inheritdoc/> [DataField("noise")]
[DataField("seedOffset")] public FastNoiseLite Noise { get; } = new(0);
public int SeedOffset { get; } = 0;
/// <inheritdoc/>
[DataField("frequency")]
public float Frequency { get; } = 0.25f;
/// <inheritdoc/> /// <inheritdoc/>
[DataField("threshold")] [DataField("threshold")]
@@ -106,18 +91,12 @@ public sealed class BiomeEntityLayer : IBiomeWorldLayer
[DataField("allowedTiles", customTypeSerializer:typeof(PrototypeIdListSerializer<ContentTileDefinition>))] [DataField("allowedTiles", customTypeSerializer:typeof(PrototypeIdListSerializer<ContentTileDefinition>))]
public List<string> AllowedTiles { get; } = new(); public List<string> AllowedTiles { get; } = new();
[DataField("noise")] public FastNoiseLite Noise { get; } = new(0);
/// <inheritdoc/> /// <inheritdoc/>
[DataField("threshold")] [DataField("threshold")]
public float Threshold { get; } = 0.5f; public float Threshold { get; } = 0.5f;
/// <inheritdoc/>
[DataField("seedOffset")]
public int SeedOffset { get; } = 0;
/// <inheritdoc/>
[DataField("frequency")]
public float Frequency { get; } = 0.1f;
[DataField("entities", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))] [DataField("entities", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Entities = new(); public List<string> Entities = new();
} }

View File

@@ -1,8 +1,5 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Content.Shared.Decals;
using Content.Shared.Maps; using Content.Shared.Maps;
using Robust.Shared.Console;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Map.Components; using Robust.Shared.Map.Components;
@@ -20,8 +17,6 @@ public abstract class SharedBiomeSystem : EntitySystem
protected const byte ChunkSize = 8; protected const byte ChunkSize = 8;
// TODO: After I wrote all of this FastNoiseLite got ported so this needs updating for that don't @ me
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
@@ -35,6 +30,8 @@ public abstract class SharedBiomeSystem : EntitySystem
return; return;
component.Seed = state.Seed; component.Seed = state.Seed;
component.BiomePrototype = state.Prototype;
component.Noise.SetSeed(component.Seed);
} }
private void OnBiomeGetState(EntityUid uid, BiomeComponent component, ref ComponentGetState args) private void OnBiomeGetState(EntityUid uid, BiomeComponent component, ref ComponentGetState args)
@@ -86,9 +83,9 @@ public abstract class SharedBiomeSystem : EntitySystem
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
public bool TryGetBiomeTile(EntityUid uid, MapGridComponent grid, Vector2i indices, [NotNullWhen(true)] out Tile? tile) public bool TryGetBiomeTile(EntityUid uid, MapGridComponent grid, FastNoiseLite noise, Vector2i indices, [NotNullWhen(true)] out Tile? tile)
{ {
if (grid.TryGetTileRef(indices, out var tileRef)) if (grid.TryGetTileRef(indices, out var tileRef) && !tileRef.Tile.IsEmpty)
{ {
tile = tileRef.Tile; tile = tileRef.Tile;
return true; return true;
@@ -101,13 +98,13 @@ public abstract class SharedBiomeSystem : EntitySystem
} }
return TryGetBiomeTile(indices, ProtoManager.Index<BiomePrototype>(biome.BiomePrototype), return TryGetBiomeTile(indices, ProtoManager.Index<BiomePrototype>(biome.BiomePrototype),
new FastNoise(biome.Seed), grid, out tile); biome.Noise, grid, out tile);
} }
/// <summary> /// <summary>
/// Tries to get the tile, real or otherwise, for the specified indices. /// Tries to get the tile, real or otherwise, for the specified indices.
/// </summary> /// </summary>
public bool TryGetBiomeTile(Vector2i indices, BiomePrototype prototype, FastNoise seed, MapGridComponent? grid, [NotNullWhen(true)] out Tile? tile) public bool TryGetBiomeTile(Vector2i indices, BiomePrototype prototype, FastNoiseLite noise, MapGridComponent? grid, [NotNullWhen(true)] out Tile? tile)
{ {
if (grid?.TryGetTileRef(indices, out var tileRef) == true && !tileRef.Tile.IsEmpty) if (grid?.TryGetTileRef(indices, out var tileRef) == true && !tileRef.Tile.IsEmpty)
{ {
@@ -115,7 +112,7 @@ public abstract class SharedBiomeSystem : EntitySystem
return true; return true;
} }
var oldFrequency = seed.GetFrequency(); var oldSeed = noise.GetSeed();
for (var i = prototype.Layers.Count - 1; i >= 0; i--) for (var i = prototype.Layers.Count - 1; i >= 0; i--)
{ {
@@ -124,179 +121,31 @@ public abstract class SharedBiomeSystem : EntitySystem
if (layer is not BiomeTileLayer tileLayer) if (layer is not BiomeTileLayer tileLayer)
continue; continue;
seed.SetFrequency(tileLayer.Frequency); SetNoise(noise, oldSeed, layer.Noise);
if (TryGetTile(indices, seed, tileLayer.Threshold, ProtoManager.Index<ContentTileDefinition>(tileLayer.Tile), tileLayer.Variants, out tile)) if (TryGetTile(indices, noise, tileLayer.Threshold, ProtoManager.Index<ContentTileDefinition>(tileLayer.Tile), tileLayer.Variants, out tile))
{ {
seed.SetFrequency(oldFrequency); noise.SetSeed(oldSeed);
return true; return true;
} }
} }
seed.SetFrequency(oldFrequency); noise.SetSeed(oldSeed);
tile = null; tile = null;
return false; return false;
} }
/// <summary>
/// Tries to get the relevant entity for this tile.
/// </summary>
protected bool TryGetEntity(Vector2i indices, BiomePrototype prototype, FastNoise noise, MapGridComponent grid,
[NotNullWhen(true)] out string? entity)
{
if (!TryGetBiomeTile(indices, prototype, noise, grid, out var tileRef))
{
entity = null;
return false;
}
var tileId = TileDefManager[tileRef.Value.TypeId].ID;
var oldFrequency = noise.GetFrequency();
var seed = noise.GetSeed();
for (var i = prototype.Layers.Count - 1; i >= 0; i--)
{
var layer = prototype.Layers[i];
var offset = 0;
// Decals might block entity so need to check if there's one in front of us.
switch (layer)
{
case IBiomeWorldLayer worldLayer:
if (!worldLayer.AllowedTiles.Contains(tileId))
continue;
offset = worldLayer.SeedOffset;
noise.SetSeed(seed + offset);
noise.SetFrequency(worldLayer.Frequency);
break;
default:
continue;
}
var value = (noise.GetCellular(indices.X, indices.Y) + 1f) / 2f;
if (value < layer.Threshold)
{
DebugTools.Assert(value is <= 1f and >= 0f);
continue;
}
if (layer is not BiomeEntityLayer biomeLayer)
{
entity = null;
noise.SetFrequency(oldFrequency);
noise.SetSeed(seed);
return false;
}
entity = Pick(biomeLayer.Entities, (noise.GetSimplex(indices.X, indices.Y) + 1f) / 2f);
noise.SetFrequency(oldFrequency);
noise.SetSeed(seed);
return true;
}
noise.SetFrequency(oldFrequency);
noise.SetSeed(seed);
entity = null;
return false;
}
/// <summary>
/// Tries to get the relevant decals for this tile.
/// </summary>
public bool TryGetDecals(Vector2i indices, BiomePrototype prototype, FastNoise noise, MapGridComponent grid,
[NotNullWhen(true)] out List<(string ID, Vector2 Position)>? decals)
{
if (!TryGetBiomeTile(indices, prototype, noise, grid, out var tileRef))
{
decals = null;
return false;
}
var tileId = TileDefManager[tileRef.Value.TypeId].ID;
var oldFrequency = noise.GetFrequency();
var seed = noise.GetSeed();
for (var i = prototype.Layers.Count - 1; i >= 0; i--)
{
var layer = prototype.Layers[i];
var offset = 0;
// Entities might block decal so need to check if there's one in front of us.
switch (layer)
{
case IBiomeWorldLayer worldLayer:
if (!worldLayer.AllowedTiles.Contains(tileId))
continue;
offset = worldLayer.SeedOffset;
noise.SetSeed(seed + offset);
noise.SetFrequency(worldLayer.Frequency);
break;
default:
continue;
}
// Check if the other layer should even render, if not then keep going.
if (layer is not BiomeDecalLayer decalLayer)
{
if ((noise.GetCellular(indices.X, indices.Y) + 1f) / 2f < layer.Threshold)
continue;
decals = null;
noise.SetFrequency(oldFrequency);
noise.SetSeed(seed);
return false;
}
decals = new List<(string ID, Vector2 Position)>();
for (var x = 0; x < decalLayer.Divisions; x++)
{
for (var y = 0; y < decalLayer.Divisions; y++)
{
var index = new Vector2(indices.X + x * 1f / decalLayer.Divisions, indices.Y + y * 1f / decalLayer.Divisions);
var decalValue = (noise.GetCellular(index.X, index.Y) + 1f) / 2f;
if (decalValue < decalLayer.Threshold)
continue;
DebugTools.Assert(decalValue is <= 1f and >= 0f);
decals.Add((Pick(decalLayer.Decals, (noise.GetSimplex(index.X, index.Y) + 1f) / 2f), index));
}
}
noise.SetFrequency(oldFrequency);
noise.SetSeed(seed);
// Check other layers
if (decals.Count == 0)
continue;
return true;
}
noise.SetFrequency(oldFrequency);
noise.SetSeed(seed);
decals = null;
return false;
}
/// <summary> /// <summary>
/// Gets the underlying biome tile, ignoring any existing tile that may be there. /// Gets the underlying biome tile, ignoring any existing tile that may be there.
/// </summary> /// </summary>
public bool TryGetTile(Vector2i indices, FastNoise seed, float threshold, ContentTileDefinition tileDef, List<byte>? variants, [NotNullWhen(true)] out Tile? tile) private bool TryGetTile(Vector2i indices, FastNoiseLite seed, float threshold, ContentTileDefinition tileDef, List<byte>? variants, [NotNullWhen(true)] out Tile? tile)
{ {
if (threshold > 0f) var found = seed.GetNoise(indices.X, indices.Y);
{
var found = (seed.GetSimplexFractal(indices.X, indices.Y) + 1f) / 2f;
if (found < threshold) if (found < threshold)
{ {
tile = null; tile = null;
return false; return false;
}
} }
byte variant = 0; byte variant = 0;
@@ -305,7 +154,7 @@ public abstract class SharedBiomeSystem : EntitySystem
// Pick a variant tile if they're available as well // Pick a variant tile if they're available as well
if (variantCount > 1) if (variantCount > 1)
{ {
var variantValue = (seed.GetSimplex(indices.X * 2f, indices.Y * 2f) + 1f) / 2f; var variantValue = (seed.GetNoise(indices.X * 8, indices.Y * 8, variantCount) + 1f) / 2f;
variant = (byte) Pick(variantCount, variantValue); variant = (byte) Pick(variantCount, variantValue);
if (variants != null) if (variants != null)
@@ -318,6 +167,157 @@ public abstract class SharedBiomeSystem : EntitySystem
return true; return true;
} }
/// <summary>
/// Tries to get the relevant entity for this tile.
/// </summary>
protected bool TryGetEntity(Vector2i indices, BiomePrototype prototype, FastNoiseLite noise, MapGridComponent grid,
[NotNullWhen(true)] out string? entity)
{
if (!TryGetBiomeTile(indices, prototype, noise, grid, out var tileRef))
{
entity = null;
return false;
}
var tileId = TileDefManager[tileRef.Value.TypeId].ID;
var oldSeed = noise.GetSeed();
for (var i = prototype.Layers.Count - 1; i >= 0; i--)
{
var layer = prototype.Layers[i];
// Decals might block entity so need to check if there's one in front of us.
switch (layer)
{
case IBiomeWorldLayer worldLayer:
if (!worldLayer.AllowedTiles.Contains(tileId))
continue;
break;
default:
continue;
}
SetNoise(noise, oldSeed, layer.Noise);
var value = noise.GetNoise(indices.X, indices.Y);
if (value < layer.Threshold)
{
continue;
}
if (layer is not BiomeEntityLayer biomeLayer)
{
entity = null;
noise.SetSeed(oldSeed);
return false;
}
entity = Pick(biomeLayer.Entities, (noise.GetNoise(indices.X, indices.Y, i) + 1f) / 2f);
noise.SetSeed(oldSeed);
return true;
}
noise.SetSeed(oldSeed);
entity = null;
return false;
}
/// <summary>
/// Tries to get the relevant decals for this tile.
/// </summary>
public bool TryGetDecals(Vector2i indices, BiomePrototype prototype, FastNoiseLite noise, MapGridComponent grid,
[NotNullWhen(true)] out List<(string ID, Vector2 Position)>? decals)
{
if (!TryGetBiomeTile(indices, prototype, noise, grid, out var tileRef))
{
decals = null;
return false;
}
var tileId = TileDefManager[tileRef.Value.TypeId].ID;
var oldSeed = noise.GetSeed();
for (var i = prototype.Layers.Count - 1; i >= 0; i--)
{
var layer = prototype.Layers[i];
// Entities might block decal so need to check if there's one in front of us.
switch (layer)
{
case IBiomeWorldLayer worldLayer:
if (!worldLayer.AllowedTiles.Contains(tileId))
continue;
break;
default:
continue;
}
SetNoise(noise, oldSeed, layer.Noise);
// Check if the other layer should even render, if not then keep going.
if (layer is not BiomeDecalLayer decalLayer)
{
if (noise.GetNoise(indices.X, indices.Y) < layer.Threshold)
continue;
decals = null;
noise.SetSeed(oldSeed);
return false;
}
decals = new List<(string ID, Vector2 Position)>();
for (var x = 0; x < decalLayer.Divisions; x++)
{
for (var y = 0; y < decalLayer.Divisions; y++)
{
var index = new Vector2(indices.X + x * 1f / decalLayer.Divisions, indices.Y + y * 1f / decalLayer.Divisions);
var decalValue = noise.GetNoise(index.X, index.Y);
if (decalValue < decalLayer.Threshold)
continue;
decals.Add((Pick(decalLayer.Decals, (noise.GetNoise(indices.X, indices.Y, x + y * decalLayer.Divisions) + 1f) / 2f), index));
}
}
// Check other layers
if (decals.Count == 0)
continue;
noise.SetSeed(oldSeed);
return true;
}
noise.SetSeed(oldSeed);
decals = null;
return false;
}
private void SetNoise(FastNoiseLite noise, int oldSeed, FastNoiseLite data)
{
// General
noise.SetSeed(oldSeed + data.GetSeed());
noise.SetFrequency(data.GetFrequency());
noise.SetNoiseType(data.GetNoiseType());
noise.GetRotationType3D();
// Fractal
noise.SetFractalType(data.GetFractalType());
noise.SetFractalOctaves(data.GetFractalOctaves());
noise.SetFractalLacunarity(data.GetFractalLacunarity());
// Cellular
noise.SetCellularDistanceFunction(data.GetCellularDistanceFunction());
noise.SetCellularReturnType(data.GetCellularReturnType());
noise.SetCellularJitter(data.GetCellularJitter());
// Domain warps require separate noise
}
[Serializable, NetSerializable] [Serializable, NetSerializable]
private sealed class BiomeComponentState : ComponentState private sealed class BiomeComponentState : ComponentState
{ {

View File

@@ -0,0 +1,11 @@
namespace Content.Shared.Procedural;
public sealed class Dungeon
{
public List<DungeonRoom> Rooms = new();
/// <summary>
/// Hashset of the tiles across all rooms.
/// </summary>
public HashSet<Vector2i> RoomTiles = new();
}

View File

@@ -0,0 +1,21 @@
using Content.Shared.Procedural.DungeonGenerators;
using Content.Shared.Procedural.PostGeneration;
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural;
[Prototype("dungeonConfig")]
public sealed class DungeonConfigPrototype : IPrototype
{
[IdDataField]
public string ID { get; } = default!;
[DataField("generator", required: true)]
public IDunGen Generator = default!;
/// <summary>
/// Ran after the main dungeon is created.
/// </summary>
[DataField("postGeneration")]
public List<IPostDunGen> PostGeneration = new();
}

View File

@@ -0,0 +1,7 @@
namespace Content.Shared.Procedural.DungeonGenerators;
[ImplicitDataDefinitionForInheritors]
public interface IDunGen
{
}

View File

@@ -0,0 +1,30 @@
using Content.Shared.Maps;
using Content.Shared.Tag;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Procedural.DungeonGenerators;
/// <summary>
/// Places rooms in pre-selected pack layouts. Chooses rooms from the specified whitelist.
/// </summary>
public sealed class PrefabDunGen : IDunGen
{
/// <summary>
/// Rooms need to match any of these tags
/// </summary>
[DataField("roomWhitelist", customTypeSerializer:typeof(PrototypeIdListSerializer<TagPrototype>))]
public List<string> RoomWhitelist = new();
/// <summary>
/// Room pack presets we can use for this prefab.
/// </summary>
[DataField("presets", required: true, customTypeSerializer:typeof(PrototypeIdListSerializer<DungeonPresetPrototype>))]
public List<string> Presets = new();
/// <summary>
/// Fallback tile.
/// </summary>
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
}

View File

@@ -0,0 +1,10 @@
namespace Content.Shared.Procedural;
/// <summary>
/// Connects 2 dungeon rooms.
/// </summary>
public sealed record DungeonPath(string Tile, string Wall, HashSet<Vector2i> Tiles)
{
public string Tile = Tile;
public string Wall = Wall;
}

View File

@@ -0,0 +1,15 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural;
[Prototype("dungeonPreset")]
public sealed class DungeonPresetPrototype : IPrototype
{
[IdDataField] public string ID { get; } = default!;
/// <summary>
/// The room pack bounds we need to fill.
/// </summary>
[DataField("roomPacks", required: true)]
public List<Box2i> RoomPacks = new();
}

View File

@@ -0,0 +1,3 @@
namespace Content.Shared.Procedural;
public sealed record DungeonRoom(HashSet<Vector2i> Tiles, Vector2 Center);

View File

@@ -0,0 +1,17 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural;
[Prototype("dungeonRoomPack")]
public sealed class DungeonRoomPackPrototype : IPrototype
{
[IdDataField]
public string ID { get; } = string.Empty;
/// <summary>
/// Used to associate the room pack with other room packs with the same dimensions.
/// </summary>
[DataField("size", required: true)] public Vector2i Size;
[DataField("rooms", required: true)] public List<Box2i> Rooms = new();
}

View File

@@ -0,0 +1,27 @@
using Content.Shared.Tag;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Robust.Shared.Utility;
namespace Content.Shared.Procedural;
[Prototype("dungeonRoom")]
public sealed class DungeonRoomPrototype : IPrototype
{
[IdDataField] public string ID { get; } = string.Empty;
[ViewVariables(VVAccess.ReadWrite), DataField("tags", customTypeSerializer:typeof(PrototypeIdListSerializer<TagPrototype>))]
public List<string> Tags = new();
[DataField("size", required: true)] public Vector2i Size;
/// <summary>
/// Path to the file to use for the room.
/// </summary>
[DataField("atlas", required: true)] public ResourcePath AtlasPath = default!;
/// <summary>
/// Tile offset into the atlas to use for the room.
/// </summary>
[DataField("offset", required: true)] public Vector2i Offset;
}

View File

@@ -0,0 +1,35 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Procedural.Loot;
/// <summary>
/// Spawns loot at points in the specified rooms
/// </summary>
public sealed class ClusterLoot : IDungeonLoot
{
/// <summary>
/// Minimum spawns in a cluster.
/// </summary>
[DataField("minCluster")]
public int MinClusterAmount;
/// <summary>
/// Maximum spawns in a cluster.
/// </summary>
[DataField("maxCluster")] public int MaxClusterAmount;
/// <summary>
/// Amount to spawn for the entire loot.
/// </summary>
[DataField("max")]
public int Amount;
/// <summary>
/// Number of points to spawn.
/// </summary>
[DataField("points")] public int Points;
[DataField("proto", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string Prototype { get; } = string.Empty;
}

View File

@@ -0,0 +1,7 @@
namespace Content.Shared.Procedural.Loot;
[ImplicitDataDefinitionForInheritors]
public interface IDungeonLoot
{
string Prototype { get; }
}

View File

@@ -0,0 +1,20 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.Loot;
/// <summary>
/// Spawned inside of a salvage mission.
/// </summary>
[Prototype("salvageLoot")]
public sealed class SalvageLootPrototype : IPrototype
{
[IdDataField] public string ID { get; } = default!;
[DataField("desc")] public string Description = string.Empty;
/// <summary>
/// All of the loot rules
/// </summary>
[DataField("loots")]
public List<IDungeonLoot> LootRules = new();
}

View File

@@ -0,0 +1,23 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Iterates room edges and places the relevant tiles and walls on any free indices.
/// </summary>
public sealed class BoundaryWallPostGen : IPostDunGen
{
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
[DataField("wall", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
public string Wall = "WallSolid";
/// <summary>
/// Walls to use in corners if applicable.
/// </summary>
[DataField("cornerWall", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
public string? CornerWall;
}

View File

@@ -0,0 +1,23 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Selects [count] rooms and places external doors to them.
/// </summary>
public sealed class EntrancePostGen : IPostDunGen
{
/// <summary>
/// How many rooms we place doors on.
/// </summary>
[DataField("count")]
public int Count = 1;
[DataField("door", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
public string Door = "AirlockGlass";
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
}

View File

@@ -0,0 +1,22 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// If external areas are found will try to generate windows.
/// </summary>
public sealed class ExternalWindowPostGen : IPostDunGen
{
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Entities = new()
{
"Grille",
"Window",
};
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
}

View File

@@ -0,0 +1,10 @@
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Ran after generating dungeon rooms. Can be used for additional loot, contents, etc.
/// </summary>
[ImplicitDataDefinitionForInheritors]
public interface IPostDunGen
{
}

View File

@@ -0,0 +1,22 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// If internal areas are found will try to generate windows.
/// </summary>
public sealed class InternalWindowPostGen : IPostDunGen
{
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Entities = new()
{
"Grille",
"Window",
};
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
}

View File

@@ -0,0 +1,39 @@
using Content.Shared.Maps;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Places the specified entities on the middle connections between rooms
/// </summary>
public sealed class MiddleConnectionPostGen : IPostDunGen
{
/// <summary>
/// How much overlap there needs to be between 2 rooms exactly.
/// </summary>
[DataField("overlapCount")]
public int OverlapCount = -1;
/// <summary>
/// How many connections to spawn between rooms.
/// </summary>
[DataField("count")]
public int Count = 1;
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
[DataField("entities", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List<string> Entities = new()
{
"CableApcExtension",
"AirlockGlass"
};
/// <summary>
/// If overlap > 1 then what should spawn on the edges.
/// </summary>
[DataField("edgeEntities")] public List<string>? EdgeEntities;
}

View File

@@ -0,0 +1,23 @@
using Content.Shared.Maps;
using Content.Shared.Storage;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Procedural.PostGeneration;
/// <summary>
/// Spawns on the boundary tiles of rooms.
/// </summary>
public sealed class WallMountPostGen : IPostDunGen
{
[DataField("tile", customTypeSerializer:typeof(PrototypeIdSerializer<ContentTileDefinition>))]
public string Tile = "FloorSteel";
[DataField("spawns")]
public List<EntitySpawnEntry> Spawns = new();
/// <summary>
/// Chance per free tile to spawn a wallmount.
/// </summary>
[DataField("prob")]
public double Prob = 0.1;
}

View File

@@ -0,0 +1,10 @@
namespace Content.Shared.Procedural.Rewards;
/// <summary>
/// Payout to the station's bank account.
/// </summary>
public sealed class BankReward : ISalvageReward
{
[DataField("amount")]
public int Amount = 0;
}

View File

@@ -0,0 +1,7 @@
namespace Content.Shared.Procedural.Rewards;
[ImplicitDataDefinitionForInheritors]
public interface ISalvageReward
{
}

View File

@@ -0,0 +1,14 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Procedural.Rewards;
/// <summary>
/// Given after successful completion of a salvage mission.
/// </summary>
[Prototype("salvageReward")]
public sealed class SalvageRewardPrototype : IPrototype
{
[IdDataField] public string ID { get; } = string.Empty;
[DataField("reward", required: true)] public ISalvageReward Reward = default!;
}

View File

@@ -11,6 +11,28 @@ namespace Content.Shared.Random.Helpers
return random.Pick(prototype.Values); return random.Pick(prototype.Values);
} }
public static string Pick(this WeightedRandomPrototype prototype, System.Random random)
{
var picks = prototype.Weights;
var sum = picks.Values.Sum();
var accumulated = 0f;
var rand = random.NextFloat() * sum;
foreach (var (key, weight) in picks)
{
accumulated += weight;
if (accumulated >= rand)
{
return key;
}
}
// Shouldn't happen
throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!");
}
public static string Pick(this WeightedRandomPrototype prototype, IRobustRandom? random = null) public static string Pick(this WeightedRandomPrototype prototype, IRobustRandom? random = null)
{ {
IoCManager.Resolve(ref random); IoCManager.Resolve(ref random);
@@ -33,5 +55,25 @@ namespace Content.Shared.Random.Helpers
// Shouldn't happen // Shouldn't happen
throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!"); throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!");
} }
public static string Pick(this IRobustRandom random, Dictionary<string, float> weights)
{
var sum = weights.Values.Sum();
var accumulated = 0f;
var rand = random.NextFloat() * sum;
foreach (var (key, weight) in weights)
{
accumulated += weight;
if (accumulated >= rand)
{
return key;
}
}
throw new InvalidOperationException($"Invalid weighted pick");
}
} }
} }

View File

@@ -0,0 +1,21 @@
namespace Content.Shared.Salvage.Expeditions.Extraction;
public sealed class SalvageExtraction : ISalvageMission
{
/// <summary>
/// Minimum weight to be used for a wave.
/// </summary>
[DataField("minWaveWeight")] public float MinWaveWeight = 5;
/// <summary>
/// Minimum time between 2 waves. Roughly the end of one to the start of another.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("waveCooldown")]
public TimeSpan WaveCooldown = TimeSpan.FromSeconds(60);
/// <summary>
/// How much weight accumulates per second while the expedition is active.
/// </summary>
[DataField("weightAccumulator")]
public float WeightAccumulator = 0.1f;
}

View File

@@ -0,0 +1,7 @@
namespace Content.Shared.Salvage.Expeditions;
public interface IFactionExpeditionConfig
{
}

View File

@@ -0,0 +1,19 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
namespace Content.Shared.Salvage.Expeditions;
[Prototype("salvageFaction")]
public sealed class SalvageFactionPrototype : IPrototype
{
[IdDataField] public string ID { get; } = default!;
[ViewVariables(VVAccess.ReadWrite), DataField("groups", required: true)]
public List<SalvageMobGroup> MobGroups = default!;
/// <summary>
/// Per expedition type data for this faction.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("configs", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<IFactionExpeditionConfig, SalvageExpeditionPrototype>))]
public Dictionary<string, IFactionExpeditionConfig> Configs = new();
}

View File

@@ -0,0 +1,18 @@
using Content.Shared.Storage;
namespace Content.Shared.Salvage.Expeditions;
[DataDefinition]
public record struct SalvageMobGroup()
{
// A mob may be cheap but rare or expensive but frequent.
/// <summary>
/// Probability to spawn this group. Summed with everything else for the faction.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("prob")]
public float Prob = 1f;
[ViewVariables(VVAccess.ReadWrite), DataField("entries", required: true)]
public List<EntitySpawnEntry> Entries = new();
}

View File

@@ -0,0 +1,17 @@
namespace Content.Shared.Salvage.Expeditions.Structure;
/// <summary>
/// Destroy the specified number of structures to finish the expedition.
/// </summary>
[DataDefinition]
public sealed class SalvageStructure : ISalvageMission
{
[DataField("desc")]
public string Description = string.Empty;
[ViewVariables(VVAccess.ReadWrite), DataField("minStructures")]
public int MinStructures = 3;
[ViewVariables(VVAccess.ReadWrite), DataField("maxStructures")]
public int MaxStructures = 5;
}

View File

@@ -0,0 +1,23 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Salvage.Expeditions.Structure;
/// <summary>
/// Per-faction config for Salvage Structure expeditions.
/// </summary>
[DataDefinition]
public sealed class SalvageStructureFaction : IFactionExpeditionConfig
{
/// <summary>
/// Entity prototype of the structures to destroy.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("spawn", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string Spawn = default!;
/// <summary>
/// How many groups of mobs to spawn.
/// </summary>
[DataField("groupCount")]
public int Groups = 5;
}

View File

@@ -0,0 +1,3 @@
namespace Content.Shared.Salvage;
public interface ISalvageMission {}

View File

@@ -0,0 +1,89 @@
using Content.Shared.Dataset;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Procedural;
using Content.Shared.Procedural.Loot;
using Content.Shared.Procedural.Rewards;
using Content.Shared.Random;
using Content.Shared.Salvage.Expeditions;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
namespace Content.Shared.Salvage;
[Prototype("salvageExpedition")]
public sealed class SalvageExpeditionPrototype : IPrototype
{
[IdDataField] public string ID { get; } = default!;
/// <summary>
/// Naming scheme for the FTL marker.
/// </summary>
[DataField("nameProto", customTypeSerializer:typeof(PrototypeIdSerializer<DatasetPrototype>))]
public string NameProto = "names_borer";
/// <summary>
/// Biome to generate the dungeon.
/// </summary>
[DataField("biome", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<BiomePrototype>))]
public string Biome = string.Empty;
/// <summary>
/// Player-friendly description for the console.
/// </summary>
[DataField("desc")]
public string Description = string.Empty;
[DataField("difficultyRating")]
public DifficultyRating DifficultyRating = DifficultyRating.Minor;
// TODO: Make these modifiers but also add difficulty modifiers.
[DataField("light")]
public Color Light = Color.Black;
[DataField("temperature")]
public float Temperature = 293.15f;
[DataField("expedition", required: true)]
public ISalvageMission Mission = default!;
[DataField("minDuration")]
public TimeSpan MinDuration = TimeSpan.FromSeconds(9 * 60);
[DataField("maxDuration")]
public TimeSpan MaxDuration = TimeSpan.FromSeconds(12 * 60);
/// <summary>
/// Available factions for selection for this mission prototype.
/// </summary>
[DataField("factions", customTypeSerializer:typeof(PrototypeIdListSerializer<SalvageFactionPrototype>))]
public List<string> Factions = new();
[DataField("dungeonConfig", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<DungeonConfigPrototype>))]
public string DungeonConfigPrototype = string.Empty;
[DataField("reward", customTypeSerializer: typeof(PrototypeIdSerializer<WeightedRandomPrototype>))]
public string Reward = string.Empty;
/// <summary>
/// Possible loot prototypes available for this expedition.
/// This spawns during the mission and is not tied to completion.
/// </summary>
[DataField("loot", customTypeSerializer: typeof(PrototypeIdListSerializer<WeightedRandomPrototype>))]
public List<string> Loots = new();
[DataField("dungeonPosition")]
public Vector2i DungeonPosition = new(80, -25);
}
[Serializable, NetSerializable]
public enum DifficultyRating : byte
{
None,
Minor,
Moderate,
Hazardous,
Extreme,
}

View File

@@ -0,0 +1,91 @@
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Salvage;
[Serializable, NetSerializable]
public sealed class SalvageExpeditionConsoleState : BoundUserInterfaceState
{
public TimeSpan NextOffer;
public bool Claimed;
public ushort ActiveMission;
public List<SalvageMission> Missions;
public SalvageExpeditionConsoleState(TimeSpan nextOffer, bool claimed, ushort activeMission, List<SalvageMission> missions)
{
NextOffer = nextOffer;
Claimed = claimed;
ActiveMission = activeMission;
Missions = missions;
}
}
/// <summary>
/// Used to interact with salvage expeditions and claim them.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed class SalvageExpeditionConsoleComponent : Component
{
}
[Serializable, NetSerializable]
public sealed class ClaimSalvageMessage : BoundUserInterfaceMessage
{
public ushort Index;
}
/// <summary>
/// Added per station to store data on their available salvage missions.
/// </summary>
[RegisterComponent]
public sealed class SalvageExpeditionDataComponent : Component
{
/// <summary>
/// Is there an active salvage expedition.
/// </summary>
[ViewVariables]
public bool Claimed => ActiveMission != 0;
/// <summary>
/// Nexy time salvage missions are offered.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("nextOffer", customTypeSerializer:typeof(TimeOffsetSerializer))]
public TimeSpan NextOffer;
[ViewVariables]
public readonly Dictionary<ushort, SalvageMission> Missions = new();
[ViewVariables] public ushort ActiveMission;
public ushort NextIndex = 1;
}
[Serializable, NetSerializable]
public sealed record SalvageMission
{
[ViewVariables]
public ushort Index;
[ViewVariables(VVAccess.ReadWrite), DataField("config", required: true, customTypeSerializer:typeof(SalvageExpeditionPrototype))]
public string Config = default!;
[ViewVariables] public TimeSpan Duration;
[ViewVariables] public int Seed;
}
[Serializable, NetSerializable]
public enum SalvageEnvironment : byte
{
Invalid = 0,
Caves,
}
[Serializable, NetSerializable]
public enum SalvageConsoleUiKey : byte
{
Expedition,
}

View File

@@ -0,0 +1,77 @@
using Content.Shared.Dataset;
using Content.Shared.Procedural.Loot;
using Content.Shared.Procedural.Rewards;
using Content.Shared.Random;
using Content.Shared.Random.Helpers;
using Content.Shared.Salvage.Expeditions.Structure;
using Robust.Shared.Prototypes;
namespace Content.Shared.Salvage;
public abstract class SharedSalvageSystem : EntitySystem
{
public static readonly TimeSpan MissionCooldown = TimeSpan.FromMinutes(5);
public static readonly TimeSpan MissionFailedCooldown = TimeSpan.FromMinutes(10);
public static float GetDifficultyModifier(DifficultyRating difficulty)
{
// These should reflect how many salvage staff are expected to be required for the mission.
switch (difficulty)
{
case DifficultyRating.None:
return 1f;
case DifficultyRating.Minor:
return 1.5f;
case DifficultyRating.Moderate:
return 3f;
case DifficultyRating.Hazardous:
return 6f;
case DifficultyRating.Extreme:
return 10f;
default:
throw new ArgumentOutOfRangeException(nameof(difficulty), difficulty, null);
}
}
public static string GetFTLName(DatasetPrototype dataset, int seed)
{
var random = new System.Random(seed);
return $"{dataset.Values[random.Next(dataset.Values.Count)]}-{random.Next(10, 100)}-{(char) (65 + random.Next(26))}";
}
public static string GetFaction(List<string> factions, int seed)
{
var adjustedSeed = new System.Random(seed + 1);
return factions[adjustedSeed.Next(factions.Count)];
}
public static IEnumerable<SalvageLootPrototype> GetLoot(List<string> loots, int seed, IPrototypeManager protoManager)
{
var adjustedSeed = new System.Random(seed + 2);
for (var i = 0; i < loots.Count; i++)
{
var loot = loots[i];
var a = protoManager.Index<WeightedRandomPrototype>(loot);
var lootConfig = a.Pick(adjustedSeed);
yield return protoManager.Index<SalvageLootPrototype>(lootConfig);
}
}
public static ISalvageReward GetReward(WeightedRandomPrototype proto, int seed, IPrototypeManager protoManager)
{
var adjustedSeed = new System.Random(seed + 3);
var rewardProto = proto.Pick(adjustedSeed);
return protoManager.Index<SalvageRewardPrototype>(rewardProto).Reward;
}
#region Structure
public static int GetStructureCount(SalvageStructure structure, int seed)
{
var adjustedSeed = new System.Random(seed + 4);
return adjustedSeed.Next(structure.MinStructures, structure.MaxStructures + 1);
}
#endregion
}

View File

@@ -131,6 +131,71 @@ public static class EntitySpawnCollection
return spawned; return spawned;
} }
public static List<string?> GetSpawns(IEnumerable<EntitySpawnEntry> entries,
System.Random random)
{
var spawned = new List<string?>();
var ungrouped = CollectOrGroups(entries, out var orGroupedSpawns);
foreach (var entry in ungrouped)
{
// Check random spawn
// ReSharper disable once CompareOfFloatsByEqualityOperator
if (entry.SpawnProbability != 1f && !random.Prob(entry.SpawnProbability))
continue;
var amount = (int) entry.GetAmount(random);
for (var i = 0; i < amount; i++)
{
spawned.Add(entry.PrototypeId);
}
}
// Handle OrGroup spawns
foreach (var spawnValue in orGroupedSpawns)
{
// For each group use the added cumulative probability to roll a double in that range
var diceRoll = random.NextDouble() * spawnValue.CumulativeProbability;
// Add the entry's spawn probability to this value, if equals or lower, spawn item, otherwise continue to next item.
var cumulative = 0.0;
foreach (var entry in spawnValue.Entries)
{
cumulative += entry.SpawnProbability;
if (diceRoll > cumulative)
continue;
// Dice roll succeeded, add item and break loop
var amount = (int) entry.GetAmount(random);
for (var i = 0; i < amount; i++)
{
spawned.Add(entry.PrototypeId);
}
break;
}
}
return spawned;
}
public static double GetAmount(this EntitySpawnEntry entry, System.Random random, bool getAverage = false)
{
// Max amount is less or equal than amount, so just return the amount
if (entry.MaxAmount <= entry.Amount)
return entry.Amount;
// If we want the average, just calculate the expected amount
if (getAverage)
return (entry.Amount + entry.MaxAmount) / 2.0;
// Otherwise get a random value in between
return random.Next(entry.Amount, entry.MaxAmount);
}
/// <summary> /// <summary>
/// Collects all entries that belong together in an OrGroup, and then returns the leftover ungrouped entries. /// Collects all entries that belong together in an OrGroup, and then returns the leftover ungrouped entries.
/// </summary> /// </summary>

View File

@@ -0,0 +1,8 @@
- files:
- water1.ogg
- water2.ogg
- water3.ogg
- water4.ogg
license: "CC-BY-SA-3.0"
copyright: "Taken from https://github.com/Citadel-Station-13/Citadel-Station-13-RP"
source: "https://github.com/Citadel-Station-13/Citadel-Station-13-RP/tree/b7392a25f826d038d35309cf36875f2066c3eb05/sound/effects/footstep"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -6,8 +6,11 @@ lobbyenabled = false
# Makes mapping annoying # Makes mapping annoying
grid_splitting = false grid_splitting = false
[procgen]
preload = false
[shuttle] [shuttle]
# Wastes startup time # Wastes startup time
auto_call_time = 0
cargo = false cargo = false
emergency_enabled = false emergency_enabled = false

View File

@@ -0,0 +1,15 @@
cmd-dungen-desc = Generates a procedural dungeon with the specified preset, position, and seed.
cmd-dungen-help = dungen <MapId> <DungeonPreset> <PosX> <PosY> [seed]
cmd-dungen-arg-count = Require 4 args.
cmd-dungen-map-parse = Unable to parse MapId.
cmd-dungen-mapgrid = Unable to find MapGrid.
cmd-dungen-config = Unable to find dungeon config.
cmd-dungen-pos = Unable to parse position.
cmd-dungen-seed = Unable to parse seed.
cmd-dungen-start = Generating dungeon with seed {$seed}
cmd-dungen-hint-map = Map Id
cmd-dungen-hint-config = Dungeon config
cmd-dungen-hint-posx = Position X
cmd-dungen-hint-posy = Position Y
cmd-dungen-hint-seed = [Seed]

View File

@@ -0,0 +1,448 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
1,0:
ind: 1,0
tiles: BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
1,1:
ind: 1,1
tiles: BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,1:
ind: 0,1
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,0:
ind: 0,0
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 56.3512981
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
16,0: 0
16,1: 0
16,2: 0
16,3: 0
16,4: 0
16,5: 0
16,6: 0
16,7: 0
16,8: 0
16,9: 0
16,10: 0
16,11: 0
16,12: 0
16,13: 0
16,14: 0
16,15: 0
16,16: 0
0,16: 0
1,16: 0
2,16: 0
3,16: 0
4,16: 0
5,16: 0
6,16: 0
7,16: 0
8,16: 0
9,16: 0
10,16: 0
11,16: 0
12,16: 0
13,16: 0
14,16: 0
15,16: 0
0,9: 0
0,10: 0
0,11: 0
0,12: 0
0,13: 0
0,14: 0
0,15: 0
1,0: 0
1,1: 0
1,2: 0
1,3: 0
1,4: 0
1,5: 0
1,6: 0
1,7: 0
1,8: 0
1,9: 0
1,10: 0
1,11: 0
1,12: 0
1,13: 0
1,14: 0
1,15: 0
2,0: 0
2,1: 0
2,2: 0
2,3: 0
2,4: 0
2,5: 0
2,6: 0
2,7: 0
2,8: 0
2,9: 0
2,10: 0
2,11: 0
2,12: 0
2,13: 0
2,14: 0
2,15: 0
3,0: 0
3,1: 0
3,2: 0
3,3: 0
3,4: 0
3,5: 0
3,6: 0
3,7: 0
3,8: 0
3,9: 0
3,10: 0
3,11: 0
3,12: 0
3,13: 0
3,14: 0
3,15: 0
4,0: 0
4,1: 0
4,2: 0
4,3: 0
4,4: 0
4,5: 0
4,6: 0
4,7: 0
4,8: 0
4,9: 0
4,10: 0
4,11: 0
4,12: 0
4,13: 0
4,14: 0
4,15: 0
5,0: 0
5,1: 0
5,2: 0
5,3: 0
5,4: 0
5,5: 0
5,6: 0
5,7: 0
5,8: 0
5,9: 0
5,10: 0
5,11: 0
5,12: 0
5,13: 0
5,14: 0
5,15: 0
6,0: 0
6,1: 0
6,2: 0
6,3: 0
6,4: 0
6,5: 0
6,6: 0
6,7: 0
6,8: 0
6,9: 0
6,10: 0
6,11: 0
6,12: 0
6,13: 0
6,14: 0
6,15: 0
7,0: 0
7,1: 0
7,2: 0
7,3: 0
7,4: 0
7,5: 0
7,6: 0
7,7: 0
7,8: 0
7,9: 0
7,10: 0
7,11: 0
7,12: 0
7,13: 0
7,14: 0
7,15: 0
8,0: 0
8,1: 0
8,2: 0
8,3: 0
8,4: 0
8,5: 0
8,6: 0
8,7: 0
8,8: 0
8,9: 0
8,10: 0
8,11: 0
8,12: 0
8,13: 0
8,14: 0
8,15: 0
9,0: 0
9,1: 0
9,2: 0
9,3: 0
9,4: 0
9,5: 0
9,6: 0
9,7: 0
9,8: 0
9,9: 0
9,10: 0
9,11: 0
9,12: 0
9,13: 0
9,14: 0
9,15: 0
10,0: 0
10,1: 0
10,2: 0
10,3: 0
10,4: 0
10,5: 0
10,6: 0
10,7: 0
10,8: 0
10,9: 0
10,10: 0
10,11: 0
10,12: 0
10,13: 0
10,14: 0
10,15: 0
11,0: 0
11,1: 0
11,2: 0
11,3: 0
11,4: 0
11,5: 0
11,6: 0
11,7: 0
11,8: 0
11,9: 0
11,10: 0
11,11: 0
11,12: 0
11,13: 0
11,14: 0
11,15: 0
12,0: 0
12,1: 0
12,2: 0
12,3: 0
12,4: 0
12,5: 0
12,6: 0
12,7: 0
12,8: 0
12,9: 0
12,10: 0
12,11: 0
12,12: 0
12,13: 0
12,14: 0
12,15: 0
13,0: 0
13,1: 0
13,2: 0
13,3: 0
13,4: 0
13,5: 0
13,6: 0
13,7: 0
13,8: 0
13,9: 0
13,10: 0
13,11: 0
13,12: 0
13,13: 0
13,14: 0
13,15: 0
14,0: 0
14,1: 0
14,2: 0
14,3: 0
14,4: 0
14,5: 0
14,6: 0
14,7: 0
14,8: 0
14,9: 0
14,10: 0
14,11: 0
14,12: 0
14,13: 0
14,14: 0
14,15: 0
15,0: 0
15,1: 0
15,2: 0
15,3: 0
15,4: 0
15,5: 0
15,6: 0
15,7: 0
15,8: 0
15,9: 0
15,10: 0
15,11: 0
15,12: 0
15,13: 0
15,14: 0
15,15: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,442 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
1,0:
ind: 1,0
tiles: BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,0:
ind: 0,0
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 56.3512981
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
16,0: 0
16,1: 0
16,2: 0
16,3: 0
16,4: 0
16,5: 0
16,6: 0
16,7: 0
16,8: 0
16,9: 0
16,10: 0
16,11: 0
16,12: 0
16,13: 0
16,14: 0
16,15: 0
16,16: 0
0,16: 0
1,16: 0
2,16: 0
3,16: 0
4,16: 0
5,16: 0
6,16: 0
7,16: 0
8,16: 0
9,16: 0
10,16: 0
11,16: 0
12,16: 0
13,16: 0
14,16: 0
15,16: 0
0,9: 0
0,10: 0
0,11: 0
0,12: 0
0,13: 0
0,14: 0
0,15: 0
1,0: 0
1,1: 0
1,2: 0
1,3: 0
1,4: 0
1,5: 0
1,6: 0
1,7: 0
1,8: 0
1,9: 0
1,10: 0
1,11: 0
1,12: 0
1,13: 0
1,14: 0
1,15: 0
2,0: 0
2,1: 0
2,2: 0
2,3: 0
2,4: 0
2,5: 0
2,6: 0
2,7: 0
2,8: 0
2,9: 0
2,10: 0
2,11: 0
2,12: 0
2,13: 0
2,14: 0
2,15: 0
3,0: 0
3,1: 0
3,2: 0
3,3: 0
3,4: 0
3,5: 0
3,6: 0
3,7: 0
3,8: 0
3,9: 0
3,10: 0
3,11: 0
3,12: 0
3,13: 0
3,14: 0
3,15: 0
4,0: 0
4,1: 0
4,2: 0
4,3: 0
4,4: 0
4,5: 0
4,6: 0
4,7: 0
4,8: 0
4,9: 0
4,10: 0
4,11: 0
4,12: 0
4,13: 0
4,14: 0
4,15: 0
5,0: 0
5,1: 0
5,2: 0
5,3: 0
5,4: 0
5,5: 0
5,6: 0
5,7: 0
5,8: 0
5,9: 0
5,10: 0
5,11: 0
5,12: 0
5,13: 0
5,14: 0
5,15: 0
6,0: 0
6,1: 0
6,2: 0
6,3: 0
6,4: 0
6,5: 0
6,6: 0
6,7: 0
6,8: 0
6,9: 0
6,10: 0
6,11: 0
6,12: 0
6,13: 0
6,14: 0
6,15: 0
7,0: 0
7,1: 0
7,2: 0
7,3: 0
7,4: 0
7,5: 0
7,6: 0
7,7: 0
7,8: 0
7,9: 0
7,10: 0
7,11: 0
7,12: 0
7,13: 0
7,14: 0
7,15: 0
8,0: 0
8,1: 0
8,2: 0
8,3: 0
8,4: 0
8,5: 0
8,6: 0
8,7: 0
8,8: 0
8,9: 0
8,10: 0
8,11: 0
8,12: 0
8,13: 0
8,14: 0
8,15: 0
9,0: 0
9,1: 0
9,2: 0
9,3: 0
9,4: 0
9,5: 0
9,6: 0
9,7: 0
9,8: 0
9,9: 0
9,10: 0
9,11: 0
9,12: 0
9,13: 0
9,14: 0
9,15: 0
10,0: 0
10,1: 0
10,2: 0
10,3: 0
10,4: 0
10,5: 0
10,6: 0
10,7: 0
10,8: 0
10,9: 0
10,10: 0
10,11: 0
10,12: 0
10,13: 0
10,14: 0
10,15: 0
11,0: 0
11,1: 0
11,2: 0
11,3: 0
11,4: 0
11,5: 0
11,6: 0
11,7: 0
11,8: 0
11,9: 0
11,10: 0
11,11: 0
11,12: 0
11,13: 0
11,14: 0
11,15: 0
12,0: 0
12,1: 0
12,2: 0
12,3: 0
12,4: 0
12,5: 0
12,6: 0
12,7: 0
12,8: 0
12,9: 0
12,10: 0
12,11: 0
12,12: 0
12,13: 0
12,14: 0
12,15: 0
13,0: 0
13,1: 0
13,2: 0
13,3: 0
13,4: 0
13,5: 0
13,6: 0
13,7: 0
13,8: 0
13,9: 0
13,10: 0
13,11: 0
13,12: 0
13,13: 0
13,14: 0
13,15: 0
14,0: 0
14,1: 0
14,2: 0
14,3: 0
14,4: 0
14,5: 0
14,6: 0
14,7: 0
14,8: 0
14,9: 0
14,10: 0
14,11: 0
14,12: 0
14,13: 0
14,14: 0
14,15: 0
15,0: 0
15,1: 0
15,2: 0
15,3: 0
15,4: 0
15,5: 0
15,6: 0
15,7: 0
15,8: 0
15,9: 0
15,10: 0
15,11: 0
15,12: 0
15,13: 0
15,14: 0
15,15: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,131 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 2.453125,1.890625
parent: invalid
type: Transform
- chunks:
-1,-1:
ind: -1,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 0.45
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
...

View File

@@ -0,0 +1,131 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 2.453125,1.890625
parent: invalid
type: Transform
- chunks:
-1,-1:
ind: -1,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 0.45
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
...

View File

@@ -0,0 +1,168 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.453125,0.890625
parent: invalid
type: Transform
- chunks:
-1,-1:
ind: -1,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAA==
0,0:
ind: 0,0
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,-1:
ind: 0,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
-1,0:
ind: -1,0
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 27.154826
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
-1,-1: 0
5,3: 0
6,0: 0
6,1: 0
6,2: 0
6,3: 0
7,0: 0
6,-1: 0
7,-1: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,442 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
0,1:
ind: 0,1
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,0:
ind: 0,0
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 78.7387785
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
16,0: 0
16,1: 0
16,2: 0
16,3: 0
16,4: 0
16,5: 0
16,6: 0
16,7: 0
16,8: 0
16,9: 0
16,10: 0
16,11: 0
16,12: 0
16,13: 0
16,14: 0
16,15: 0
16,16: 0
0,16: 0
1,16: 0
2,16: 0
3,16: 0
4,16: 0
5,16: 0
6,16: 0
7,16: 0
8,16: 0
9,16: 0
10,16: 0
11,16: 0
12,16: 0
13,16: 0
14,16: 0
15,16: 0
0,9: 0
0,10: 0
0,11: 0
0,12: 0
0,13: 0
0,14: 0
0,15: 0
1,0: 0
1,1: 0
1,2: 0
1,3: 0
1,4: 0
1,5: 0
1,6: 0
1,7: 0
1,8: 0
1,9: 0
1,10: 0
1,11: 0
1,12: 0
1,13: 0
1,14: 0
1,15: 0
2,0: 0
2,1: 0
2,2: 0
2,3: 0
2,4: 0
2,5: 0
2,6: 0
2,7: 0
2,8: 0
2,9: 0
2,10: 0
2,11: 0
2,12: 0
2,13: 0
2,14: 0
2,15: 0
3,0: 0
3,1: 0
3,2: 0
3,3: 0
3,4: 0
3,5: 0
3,6: 0
3,7: 0
3,8: 0
3,9: 0
3,10: 0
3,11: 0
3,12: 0
3,13: 0
3,14: 0
3,15: 0
4,0: 0
4,1: 0
4,2: 0
4,3: 0
4,4: 0
4,5: 0
4,6: 0
4,7: 0
4,8: 0
4,9: 0
4,10: 0
4,11: 0
4,12: 0
4,13: 0
4,14: 0
4,15: 0
5,0: 0
5,1: 0
5,2: 0
5,3: 0
5,4: 0
5,5: 0
5,6: 0
5,7: 0
5,8: 0
5,9: 0
5,10: 0
5,11: 0
5,12: 0
5,13: 0
5,14: 0
5,15: 0
6,0: 0
6,1: 0
6,2: 0
6,3: 0
6,4: 0
6,5: 0
6,6: 0
6,7: 0
6,8: 0
6,9: 0
6,10: 0
6,11: 0
6,12: 0
6,13: 0
6,14: 0
6,15: 0
7,0: 0
7,1: 0
7,2: 0
7,3: 0
7,4: 0
7,5: 0
7,6: 0
7,7: 0
7,8: 0
7,9: 0
7,10: 0
7,11: 0
7,12: 0
7,13: 0
7,14: 0
7,15: 0
8,0: 0
8,1: 0
8,2: 0
8,3: 0
8,4: 0
8,5: 0
8,6: 0
8,7: 0
8,8: 0
8,9: 0
8,10: 0
8,11: 0
8,12: 0
8,13: 0
8,14: 0
8,15: 0
9,0: 0
9,1: 0
9,2: 0
9,3: 0
9,4: 0
9,5: 0
9,6: 0
9,7: 0
9,8: 0
9,9: 0
9,10: 0
9,11: 0
9,12: 0
9,13: 0
9,14: 0
9,15: 0
10,0: 0
10,1: 0
10,2: 0
10,3: 0
10,4: 0
10,5: 0
10,6: 0
10,7: 0
10,8: 0
10,9: 0
10,10: 0
10,11: 0
10,12: 0
10,13: 0
10,14: 0
10,15: 0
11,0: 0
11,1: 0
11,2: 0
11,3: 0
11,4: 0
11,5: 0
11,6: 0
11,7: 0
11,8: 0
11,9: 0
11,10: 0
11,11: 0
11,12: 0
11,13: 0
11,14: 0
11,15: 0
12,0: 0
12,1: 0
12,2: 0
12,3: 0
12,4: 0
12,5: 0
12,6: 0
12,7: 0
12,8: 0
12,9: 0
12,10: 0
12,11: 0
12,12: 0
12,13: 0
12,14: 0
12,15: 0
13,0: 0
13,1: 0
13,2: 0
13,3: 0
13,4: 0
13,5: 0
13,6: 0
13,7: 0
13,8: 0
13,9: 0
13,10: 0
13,11: 0
13,12: 0
13,13: 0
13,14: 0
13,15: 0
14,0: 0
14,1: 0
14,2: 0
14,3: 0
14,4: 0
14,5: 0
14,6: 0
14,7: 0
14,8: 0
14,9: 0
14,10: 0
14,11: 0
14,12: 0
14,13: 0
14,14: 0
14,15: 0
15,0: 0
15,1: 0
15,2: 0
15,3: 0
15,4: 0
15,5: 0
15,6: 0
15,7: 0
15,8: 0
15,9: 0
15,10: 0
15,11: 0
15,12: 0
15,13: 0
15,14: 0
15,15: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,439 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
0,0:
ind: 0,0
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAYAAAAGAAAABgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 207.9113983
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
16,0: 0
16,1: 0
16,2: 0
16,3: 0
16,4: 0
16,5: 0
16,6: 0
16,7: 0
16,8: 0
16,9: 0
16,10: 0
16,11: 0
16,12: 0
16,13: 0
16,14: 0
16,15: 0
16,16: 0
0,16: 0
1,16: 0
2,16: 0
3,16: 0
4,16: 0
5,16: 0
6,16: 0
7,16: 0
8,16: 0
9,16: 0
10,16: 0
11,16: 0
12,16: 0
13,16: 0
14,16: 0
15,16: 0
0,9: 0
0,10: 0
0,11: 0
0,12: 0
0,13: 0
0,14: 0
0,15: 0
1,0: 0
1,1: 0
1,2: 0
1,3: 0
1,4: 0
1,5: 0
1,6: 0
1,7: 0
1,8: 0
1,9: 0
1,10: 0
1,11: 0
1,12: 0
1,13: 0
1,14: 0
1,15: 0
2,0: 0
2,1: 0
2,2: 0
2,3: 0
2,4: 0
2,5: 0
2,6: 0
2,7: 0
2,8: 0
2,9: 0
2,10: 0
2,11: 0
2,12: 0
2,13: 0
2,14: 0
2,15: 0
3,0: 0
3,1: 0
3,2: 0
3,3: 0
3,4: 0
3,5: 0
3,6: 0
3,7: 0
3,8: 0
3,9: 0
3,10: 0
3,11: 0
3,12: 0
3,13: 0
3,14: 0
3,15: 0
4,0: 0
4,1: 0
4,2: 0
4,3: 0
4,4: 0
4,5: 0
4,6: 0
4,7: 0
4,8: 0
4,9: 0
4,10: 0
4,11: 0
4,12: 0
4,13: 0
4,14: 0
4,15: 0
5,0: 0
5,1: 0
5,2: 0
5,3: 0
5,4: 0
5,5: 0
5,6: 0
5,7: 0
5,8: 0
5,9: 0
5,10: 0
5,11: 0
5,12: 0
5,13: 0
5,14: 0
5,15: 0
6,0: 0
6,1: 0
6,2: 0
6,3: 0
6,4: 0
6,5: 0
6,6: 0
6,7: 0
6,8: 0
6,9: 0
6,10: 0
6,11: 0
6,12: 0
6,13: 0
6,14: 0
6,15: 0
7,0: 0
7,1: 0
7,2: 0
7,3: 0
7,4: 0
7,5: 0
7,6: 0
7,7: 0
7,8: 0
7,9: 0
7,10: 0
7,11: 0
7,12: 0
7,13: 0
7,14: 0
7,15: 0
8,0: 0
8,1: 0
8,2: 0
8,3: 0
8,4: 0
8,5: 0
8,6: 0
8,7: 0
8,8: 0
8,9: 0
8,10: 0
8,11: 0
8,12: 0
8,13: 0
8,14: 0
8,15: 0
9,0: 0
9,1: 0
9,2: 0
9,3: 0
9,4: 0
9,5: 0
9,6: 0
9,7: 0
9,8: 0
9,9: 0
9,10: 0
9,11: 0
9,12: 0
9,13: 0
9,14: 0
9,15: 0
10,0: 0
10,1: 0
10,2: 0
10,3: 0
10,4: 0
10,5: 0
10,6: 0
10,7: 0
10,8: 0
10,9: 0
10,10: 0
10,11: 0
10,12: 0
10,13: 0
10,14: 0
10,15: 0
11,0: 0
11,1: 0
11,2: 0
11,3: 0
11,4: 0
11,5: 0
11,6: 0
11,7: 0
11,8: 0
11,9: 0
11,10: 0
11,11: 0
11,12: 0
11,13: 0
11,14: 0
11,15: 0
12,0: 0
12,1: 0
12,2: 0
12,3: 0
12,4: 0
12,5: 0
12,6: 0
12,7: 0
12,8: 0
12,9: 0
12,10: 0
12,11: 0
12,12: 0
12,13: 0
12,14: 0
12,15: 0
13,0: 0
13,1: 0
13,2: 0
13,3: 0
13,4: 0
13,5: 0
13,6: 0
13,7: 0
13,8: 0
13,9: 0
13,10: 0
13,11: 0
13,12: 0
13,13: 0
13,14: 0
13,15: 0
14,0: 0
14,1: 0
14,2: 0
14,3: 0
14,4: 0
14,5: 0
14,6: 0
14,7: 0
14,8: 0
14,9: 0
14,10: 0
14,11: 0
14,12: 0
14,13: 0
14,14: 0
14,15: 0
15,0: 0
15,1: 0
15,2: 0
15,3: 0
15,4: 0
15,5: 0
15,6: 0
15,7: 0
15,8: 0
15,9: 0
15,10: 0
15,11: 0
15,12: 0
15,13: 0
15,14: 0
15,15: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,168 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
1,0:
ind: 1,0
tiles: BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
1,1:
ind: 1,1
tiles: BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,1:
ind: 0,1
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,0:
ind: 0,0
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAABEAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAARAAAAEQAAABEAAAARAAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 56.3512981
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,168 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
1,0:
ind: 1,0
tiles: BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
1,1:
ind: 1,1
tiles: BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,1:
ind: 0,1
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,0:
ind: 0,0
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAABgAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAAAGAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAABgAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAAAGAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 56.3512981
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,168 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
1,0:
ind: 1,0
tiles: BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
1,1:
ind: 1,1
tiles: BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,1:
ind: 0,1
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,0:
ind: 0,0
tiles: BgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAEQAAABEAAAARAAAAEQAAABEAAAABgAAAAYAAAAGAAAABgAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAABEAAAARAAAAEQAAABEAAAARAAAAAYAAAAGAAAABgAAAAYAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAARAAAAEQAAABEAAAARAAAAEQAAAAGAAAABgAAAAYAAAAGAAAABgAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 56.3512981
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,442 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
0,1:
ind: 0,1
tiles: RAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,0:
ind: 0,0
tiles: RAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAARAAAAEQAAABEAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAARAAAAEQAAABEAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAARAAAAEQAAABEAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 78.7387785
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
16,0: 0
16,1: 0
16,2: 0
16,3: 0
16,4: 0
16,5: 0
16,6: 0
16,7: 0
16,8: 0
16,9: 0
16,10: 0
16,11: 0
16,12: 0
16,13: 0
16,14: 0
16,15: 0
16,16: 0
0,16: 0
1,16: 0
2,16: 0
3,16: 0
4,16: 0
5,16: 0
6,16: 0
7,16: 0
8,16: 0
9,16: 0
10,16: 0
11,16: 0
12,16: 0
13,16: 0
14,16: 0
15,16: 0
0,9: 0
0,10: 0
0,11: 0
0,12: 0
0,13: 0
0,14: 0
0,15: 0
1,0: 0
1,1: 0
1,2: 0
1,3: 0
1,4: 0
1,5: 0
1,6: 0
1,7: 0
1,8: 0
1,9: 0
1,10: 0
1,11: 0
1,12: 0
1,13: 0
1,14: 0
1,15: 0
2,0: 0
2,1: 0
2,2: 0
2,3: 0
2,4: 0
2,5: 0
2,6: 0
2,7: 0
2,8: 0
2,9: 0
2,10: 0
2,11: 0
2,12: 0
2,13: 0
2,14: 0
2,15: 0
3,0: 0
3,1: 0
3,2: 0
3,3: 0
3,4: 0
3,5: 0
3,6: 0
3,7: 0
3,8: 0
3,9: 0
3,10: 0
3,11: 0
3,12: 0
3,13: 0
3,14: 0
3,15: 0
4,0: 0
4,1: 0
4,2: 0
4,3: 0
4,4: 0
4,5: 0
4,6: 0
4,7: 0
4,8: 0
4,9: 0
4,10: 0
4,11: 0
4,12: 0
4,13: 0
4,14: 0
4,15: 0
5,0: 0
5,1: 0
5,2: 0
5,3: 0
5,4: 0
5,5: 0
5,6: 0
5,7: 0
5,8: 0
5,9: 0
5,10: 0
5,11: 0
5,12: 0
5,13: 0
5,14: 0
5,15: 0
6,0: 0
6,1: 0
6,2: 0
6,3: 0
6,4: 0
6,5: 0
6,6: 0
6,7: 0
6,8: 0
6,9: 0
6,10: 0
6,11: 0
6,12: 0
6,13: 0
6,14: 0
6,15: 0
7,0: 0
7,1: 0
7,2: 0
7,3: 0
7,4: 0
7,5: 0
7,6: 0
7,7: 0
7,8: 0
7,9: 0
7,10: 0
7,11: 0
7,12: 0
7,13: 0
7,14: 0
7,15: 0
8,0: 0
8,1: 0
8,2: 0
8,3: 0
8,4: 0
8,5: 0
8,6: 0
8,7: 0
8,8: 0
8,9: 0
8,10: 0
8,11: 0
8,12: 0
8,13: 0
8,14: 0
8,15: 0
9,0: 0
9,1: 0
9,2: 0
9,3: 0
9,4: 0
9,5: 0
9,6: 0
9,7: 0
9,8: 0
9,9: 0
9,10: 0
9,11: 0
9,12: 0
9,13: 0
9,14: 0
9,15: 0
10,0: 0
10,1: 0
10,2: 0
10,3: 0
10,4: 0
10,5: 0
10,6: 0
10,7: 0
10,8: 0
10,9: 0
10,10: 0
10,11: 0
10,12: 0
10,13: 0
10,14: 0
10,15: 0
11,0: 0
11,1: 0
11,2: 0
11,3: 0
11,4: 0
11,5: 0
11,6: 0
11,7: 0
11,8: 0
11,9: 0
11,10: 0
11,11: 0
11,12: 0
11,13: 0
11,14: 0
11,15: 0
12,0: 0
12,1: 0
12,2: 0
12,3: 0
12,4: 0
12,5: 0
12,6: 0
12,7: 0
12,8: 0
12,9: 0
12,10: 0
12,11: 0
12,12: 0
12,13: 0
12,14: 0
12,15: 0
13,0: 0
13,1: 0
13,2: 0
13,3: 0
13,4: 0
13,5: 0
13,6: 0
13,7: 0
13,8: 0
13,9: 0
13,10: 0
13,11: 0
13,12: 0
13,13: 0
13,14: 0
13,15: 0
14,0: 0
14,1: 0
14,2: 0
14,3: 0
14,4: 0
14,5: 0
14,6: 0
14,7: 0
14,8: 0
14,9: 0
14,10: 0
14,11: 0
14,12: 0
14,13: 0
14,14: 0
14,15: 0
15,0: 0
15,1: 0
15,2: 0
15,3: 0
15,4: 0
15,5: 0
15,6: 0
15,7: 0
15,8: 0
15,9: 0
15,10: 0
15,11: 0
15,12: 0
15,13: 0
15,14: 0
15,15: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,442 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
0,1:
ind: 0,1
tiles: BgAAAEQAAABEAAAARAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,0:
ind: 0,0
tiles: RAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAARAAAAEQAAABEAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAARAAAAEQAAABEAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAEQAAABEAAAARAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAABEAAAARAAAAEQAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAARAAAAEQAAABEAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAEQAAABEAAAARAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 78.7387785
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
16,0: 0
16,1: 0
16,2: 0
16,3: 0
16,4: 0
16,5: 0
16,6: 0
16,7: 0
16,8: 0
16,9: 0
16,10: 0
16,11: 0
16,12: 0
16,13: 0
16,14: 0
16,15: 0
16,16: 0
0,16: 0
1,16: 0
2,16: 0
3,16: 0
4,16: 0
5,16: 0
6,16: 0
7,16: 0
8,16: 0
9,16: 0
10,16: 0
11,16: 0
12,16: 0
13,16: 0
14,16: 0
15,16: 0
0,9: 0
0,10: 0
0,11: 0
0,12: 0
0,13: 0
0,14: 0
0,15: 0
1,0: 0
1,1: 0
1,2: 0
1,3: 0
1,4: 0
1,5: 0
1,6: 0
1,7: 0
1,8: 0
1,9: 0
1,10: 0
1,11: 0
1,12: 0
1,13: 0
1,14: 0
1,15: 0
2,0: 0
2,1: 0
2,2: 0
2,3: 0
2,4: 0
2,5: 0
2,6: 0
2,7: 0
2,8: 0
2,9: 0
2,10: 0
2,11: 0
2,12: 0
2,13: 0
2,14: 0
2,15: 0
3,0: 0
3,1: 0
3,2: 0
3,3: 0
3,4: 0
3,5: 0
3,6: 0
3,7: 0
3,8: 0
3,9: 0
3,10: 0
3,11: 0
3,12: 0
3,13: 0
3,14: 0
3,15: 0
4,0: 0
4,1: 0
4,2: 0
4,3: 0
4,4: 0
4,5: 0
4,6: 0
4,7: 0
4,8: 0
4,9: 0
4,10: 0
4,11: 0
4,12: 0
4,13: 0
4,14: 0
4,15: 0
5,0: 0
5,1: 0
5,2: 0
5,3: 0
5,4: 0
5,5: 0
5,6: 0
5,7: 0
5,8: 0
5,9: 0
5,10: 0
5,11: 0
5,12: 0
5,13: 0
5,14: 0
5,15: 0
6,0: 0
6,1: 0
6,2: 0
6,3: 0
6,4: 0
6,5: 0
6,6: 0
6,7: 0
6,8: 0
6,9: 0
6,10: 0
6,11: 0
6,12: 0
6,13: 0
6,14: 0
6,15: 0
7,0: 0
7,1: 0
7,2: 0
7,3: 0
7,4: 0
7,5: 0
7,6: 0
7,7: 0
7,8: 0
7,9: 0
7,10: 0
7,11: 0
7,12: 0
7,13: 0
7,14: 0
7,15: 0
8,0: 0
8,1: 0
8,2: 0
8,3: 0
8,4: 0
8,5: 0
8,6: 0
8,7: 0
8,8: 0
8,9: 0
8,10: 0
8,11: 0
8,12: 0
8,13: 0
8,14: 0
8,15: 0
9,0: 0
9,1: 0
9,2: 0
9,3: 0
9,4: 0
9,5: 0
9,6: 0
9,7: 0
9,8: 0
9,9: 0
9,10: 0
9,11: 0
9,12: 0
9,13: 0
9,14: 0
9,15: 0
10,0: 0
10,1: 0
10,2: 0
10,3: 0
10,4: 0
10,5: 0
10,6: 0
10,7: 0
10,8: 0
10,9: 0
10,10: 0
10,11: 0
10,12: 0
10,13: 0
10,14: 0
10,15: 0
11,0: 0
11,1: 0
11,2: 0
11,3: 0
11,4: 0
11,5: 0
11,6: 0
11,7: 0
11,8: 0
11,9: 0
11,10: 0
11,11: 0
11,12: 0
11,13: 0
11,14: 0
11,15: 0
12,0: 0
12,1: 0
12,2: 0
12,3: 0
12,4: 0
12,5: 0
12,6: 0
12,7: 0
12,8: 0
12,9: 0
12,10: 0
12,11: 0
12,12: 0
12,13: 0
12,14: 0
12,15: 0
13,0: 0
13,1: 0
13,2: 0
13,3: 0
13,4: 0
13,5: 0
13,6: 0
13,7: 0
13,8: 0
13,9: 0
13,10: 0
13,11: 0
13,12: 0
13,13: 0
13,14: 0
13,15: 0
14,0: 0
14,1: 0
14,2: 0
14,3: 0
14,4: 0
14,5: 0
14,6: 0
14,7: 0
14,8: 0
14,9: 0
14,10: 0
14,11: 0
14,12: 0
14,13: 0
14,14: 0
14,15: 0
15,0: 0
15,1: 0
15,2: 0
15,3: 0
15,4: 0
15,5: 0
15,6: 0
15,7: 0
15,8: 0
15,9: 0
15,10: 0
15,11: 0
15,12: 0
15,13: 0
15,14: 0
15,15: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

View File

@@ -0,0 +1,442 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- pos: 0.75,1.3125
parent: invalid
type: Transform
- chunks:
0,1:
ind: 0,1
tiles: BgAAAEQAAABEAAAARAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,0:
ind: 0,0
tiles: BgAAAEQAAABEAAAARAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAABEAAAARAAAAEQAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAARAAAAEQAAABEAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAEQAAABEAAAARAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAABEAAAARAAAAEQAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAARAAAAEQAAABEAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEQAAABEAAAARAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABEAAAARAAAAEQAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAABgAAAAYAAAAGAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAEQAAABEAAAARAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAABEAAAARAAAAEQAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAARAAAAEQAAABEAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAEQAAABEAAAARAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
type: MapGrid
- type: Broadphase
- angularDamping: 0.05
linearDamping: 0.05
fixedRotation: False
bodyType: Dynamic
type: Physics
- fixtures: []
type: Fixtures
- type: OccluderTree
- type: Shuttle
- nextUpdate: 78.7387785
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
- tiles:
0,0: 0
0,1: 0
0,2: 0
0,3: 0
0,4: 0
0,5: 0
0,6: 0
0,7: 0
0,8: 0
16,0: 0
16,1: 0
16,2: 0
16,3: 0
16,4: 0
16,5: 0
16,6: 0
16,7: 0
16,8: 0
16,9: 0
16,10: 0
16,11: 0
16,12: 0
16,13: 0
16,14: 0
16,15: 0
16,16: 0
0,16: 0
1,16: 0
2,16: 0
3,16: 0
4,16: 0
5,16: 0
6,16: 0
7,16: 0
8,16: 0
9,16: 0
10,16: 0
11,16: 0
12,16: 0
13,16: 0
14,16: 0
15,16: 0
0,9: 0
0,10: 0
0,11: 0
0,12: 0
0,13: 0
0,14: 0
0,15: 0
1,0: 0
1,1: 0
1,2: 0
1,3: 0
1,4: 0
1,5: 0
1,6: 0
1,7: 0
1,8: 0
1,9: 0
1,10: 0
1,11: 0
1,12: 0
1,13: 0
1,14: 0
1,15: 0
2,0: 0
2,1: 0
2,2: 0
2,3: 0
2,4: 0
2,5: 0
2,6: 0
2,7: 0
2,8: 0
2,9: 0
2,10: 0
2,11: 0
2,12: 0
2,13: 0
2,14: 0
2,15: 0
3,0: 0
3,1: 0
3,2: 0
3,3: 0
3,4: 0
3,5: 0
3,6: 0
3,7: 0
3,8: 0
3,9: 0
3,10: 0
3,11: 0
3,12: 0
3,13: 0
3,14: 0
3,15: 0
4,0: 0
4,1: 0
4,2: 0
4,3: 0
4,4: 0
4,5: 0
4,6: 0
4,7: 0
4,8: 0
4,9: 0
4,10: 0
4,11: 0
4,12: 0
4,13: 0
4,14: 0
4,15: 0
5,0: 0
5,1: 0
5,2: 0
5,3: 0
5,4: 0
5,5: 0
5,6: 0
5,7: 0
5,8: 0
5,9: 0
5,10: 0
5,11: 0
5,12: 0
5,13: 0
5,14: 0
5,15: 0
6,0: 0
6,1: 0
6,2: 0
6,3: 0
6,4: 0
6,5: 0
6,6: 0
6,7: 0
6,8: 0
6,9: 0
6,10: 0
6,11: 0
6,12: 0
6,13: 0
6,14: 0
6,15: 0
7,0: 0
7,1: 0
7,2: 0
7,3: 0
7,4: 0
7,5: 0
7,6: 0
7,7: 0
7,8: 0
7,9: 0
7,10: 0
7,11: 0
7,12: 0
7,13: 0
7,14: 0
7,15: 0
8,0: 0
8,1: 0
8,2: 0
8,3: 0
8,4: 0
8,5: 0
8,6: 0
8,7: 0
8,8: 0
8,9: 0
8,10: 0
8,11: 0
8,12: 0
8,13: 0
8,14: 0
8,15: 0
9,0: 0
9,1: 0
9,2: 0
9,3: 0
9,4: 0
9,5: 0
9,6: 0
9,7: 0
9,8: 0
9,9: 0
9,10: 0
9,11: 0
9,12: 0
9,13: 0
9,14: 0
9,15: 0
10,0: 0
10,1: 0
10,2: 0
10,3: 0
10,4: 0
10,5: 0
10,6: 0
10,7: 0
10,8: 0
10,9: 0
10,10: 0
10,11: 0
10,12: 0
10,13: 0
10,14: 0
10,15: 0
11,0: 0
11,1: 0
11,2: 0
11,3: 0
11,4: 0
11,5: 0
11,6: 0
11,7: 0
11,8: 0
11,9: 0
11,10: 0
11,11: 0
11,12: 0
11,13: 0
11,14: 0
11,15: 0
12,0: 0
12,1: 0
12,2: 0
12,3: 0
12,4: 0
12,5: 0
12,6: 0
12,7: 0
12,8: 0
12,9: 0
12,10: 0
12,11: 0
12,12: 0
12,13: 0
12,14: 0
12,15: 0
13,0: 0
13,1: 0
13,2: 0
13,3: 0
13,4: 0
13,5: 0
13,6: 0
13,7: 0
13,8: 0
13,9: 0
13,10: 0
13,11: 0
13,12: 0
13,13: 0
13,14: 0
13,15: 0
14,0: 0
14,1: 0
14,2: 0
14,3: 0
14,4: 0
14,5: 0
14,6: 0
14,7: 0
14,8: 0
14,9: 0
14,10: 0
14,11: 0
14,12: 0
14,13: 0
14,14: 0
14,15: 0
15,0: 0
15,1: 0
15,2: 0
15,3: 0
15,4: 0
15,5: 0
15,6: 0
15,7: 0
15,8: 0
15,9: 0
15,10: 0
15,11: 0
15,12: 0
15,13: 0
15,14: 0
15,15: 0
uniqueMixes:
- volume: 2500
temperature: 293.15
moles:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
type: GridAtmosphere
- type: GasTileOverlay
...

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,166 @@
meta:
format: 3
name: DemoStation
author: Space-Wizards
postmapinit: false
tilemap:
0: Space
1: FloorArcadeBlue
2: FloorArcadeBlue2
3: FloorArcadeRed
4: FloorAsteroidCoarseSand0
5: FloorAsteroidCoarseSandDug
6: FloorAsteroidIronsand1
7: FloorAsteroidIronsand2
8: FloorAsteroidIronsand3
9: FloorAsteroidIronsand4
10: FloorAsteroidSand
11: FloorAsteroidTile
12: FloorBar
13: FloorBasalt
14: FloorBasaslt
15: FloorBlue
16: FloorBlueCircuit
17: FloorBoxing
18: FloorCarpetClown
19: FloorCarpetOffice
20: FloorCave
21: FloorCaveDrought
22: FloorClown
23: FloorDark
24: FloorDarkDiagonal
25: FloorDarkDiagonalMini
26: FloorDarkHerringbone
27: FloorDarkMini
28: FloorDarkMono
29: FloorDarkOffset
30: FloorDarkPavement
31: FloorDarkPavementVertical
32: FloorDarkPlastic
33: FloorDesert
34: FloorDirt
35: FloorEighties
36: FloorElevatorShaft
37: FloorFlesh
38: FloorFreezer
39: FloorGlass
40: FloorGold
41: FloorGrass
42: FloorGrassDark
43: FloorGrassJungle
44: FloorGrassLight
45: FloorGreenCircuit
46: FloorGym
47: FloorHydro
48: FloorKitchen
49: FloorLaundry
50: FloorLino
51: FloorLowDesert
52: FloorMetalDiamond
53: FloorMime
54: FloorMono
55: FloorPlanetGrass
56: FloorPlastic
57: FloorRGlass
58: FloorReinforced
59: FloorRockVault
60: FloorShowroom
61: FloorShuttleBlue
62: FloorShuttleOrange
63: FloorShuttlePurple
64: FloorShuttleRed
65: FloorShuttleWhite
66: FloorSilver
67: FloorSnow
68: FloorSteel
69: FloorSteelDiagonal
70: FloorSteelDiagonalMini
71: FloorSteelDirty
72: FloorSteelHerringbone
73: FloorSteelMini
74: FloorSteelMono
75: FloorSteelOffset
76: FloorSteelPavement
77: FloorSteelPavementVertical
78: FloorTechMaint
79: FloorTechMaint2
80: FloorTechMaint3
81: FloorWhite
82: FloorWhiteDiagonal
83: FloorWhiteDiagonalMini
84: FloorWhiteHerringbone
85: FloorWhiteMini
86: FloorWhiteMono
87: FloorWhiteOffset
88: FloorWhitePavement
89: FloorWhitePavementVertical
90: FloorWhitePlastic
91: FloorWood
92: FloorWoodTile
93: Lattice
94: Plating
entities:
- uid: 0
components:
- type: MetaData
- type: Transform
- index: 2
type: Map
- type: PhysicsMap
- type: Broadphase
- type: OccluderTree
- chunks:
-1,-1:
ind: -1,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAA==
0,0:
ind: 0,0
tiles: RAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAAPgAAAD4AAAA+AAAAPgAAAD4AAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAA==
0,1:
ind: 0,1
tiles: RAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAEQAAABEAAAARAAAAEQAAABEAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAA==
0,-1:
ind: 0,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAA==
-1,0:
ind: -1,0
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAA==
-1,1:
ind: -1,1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAA==
1,-1:
ind: 1,-1
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
1,0:
ind: 1,0
tiles: RAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
1,1:
ind: 1,1
tiles: PgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
-1,2:
ind: -1,2
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
-1,3:
ind: -1,3
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,2:
ind: 0,2
tiles: RAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAEQAAABEAAAARAAAAEQAAABEAAAARAAAAEQAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAABEAAAARAAAAEQAAABEAAAARAAAAEQAAABEAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
0,3:
ind: 0,3
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
1,2:
ind: 1,2
tiles: PgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
1,3:
ind: 1,3
tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
type: MapGrid
- nextUpdate: 171.4322096
type: GridPathfinding
- gravityShakeSound: !type:SoundPathSpecifier
path: /Audio/Effects/alert.ogg
type: Gravity
- chunkCollection: {}
type: DecalGrid
...

View File

@@ -12,7 +12,6 @@
I rigged the area where our stuff's at to be a toasty thousand K. I rigged the area where our stuff's at to be a toasty thousand K.
You know how to drain it when we need it out. You know how to drain it when we need it out.
- J. - J.
# ---- GAMING ---- # ---- GAMING ----
- type: entity - type: entity
@@ -46,7 +45,6 @@
Leaving this so you know what's up. Leaving this so you know what's up.
Sorry. Sorry.
- Alexander - Alexander
- type: entity - type: entity
id: PaperWrittenSalvageLoreGaming2 id: PaperWrittenSalvageLoreGaming2
noSpawn: true # keep this from spamming spawn sheet noSpawn: true # keep this from spamming spawn sheet
@@ -64,11 +62,9 @@
Int: 528,491 Int: 528,491
Wis: 1 Wis: 1
Cha: 1 Cha: 1
Where's the age? Where's the age?
Why are those ability scores so ridiculous? Why are those ability scores so ridiculous?
What even are you trying to do here, Leah? - Your Friendly DM What even are you trying to do here, Leah? - Your Friendly DM
- type: entity - type: entity
id: PaperWrittenSalvageLoreGaming3 id: PaperWrittenSalvageLoreGaming3
noSpawn: true # keep this from spamming spawn sheet noSpawn: true # keep this from spamming spawn sheet
@@ -83,7 +79,6 @@
Session 3: On their way to underground lair. Session 3: On their way to underground lair.
Session 4: Just ran into the Architect Of Flies. Session 4: Just ran into the Architect Of Flies.
Oh dear goodness they just started randomly killing everybody Oh dear goodness they just started randomly killing everybody
- type: entity - type: entity
id: PaperWrittenSalvageLoreGaming4 id: PaperWrittenSalvageLoreGaming4
noSpawn: true # keep this from spamming spawn sheet noSpawn: true # keep this from spamming spawn sheet
@@ -97,6 +92,4 @@
It's amazing. It's amazing.
But not in a good way. But not in a good way.
Cheers, - Arielle Cheers, - Arielle
# ---- # ----

View File

@@ -60,7 +60,7 @@
- type: MobThresholds - type: MobThresholds
thresholds: thresholds:
0: Alive 0: Alive
200: Dead 50: Dead
- type: Stamina - type: Stamina
excess: 200 excess: 200
- type: Bloodstream - type: Bloodstream
@@ -81,7 +81,7 @@
animation: WeaponArcBite animation: WeaponArcBite
damage: damage:
groups: groups:
Brute: 12 Brute: 6
- type: Appearance - type: Appearance
- type: DamageStateVisuals - type: DamageStateVisuals
rotate: true rotate: true
@@ -139,7 +139,7 @@
- type: MobThresholds - type: MobThresholds
thresholds: thresholds:
0: Alive 0: Alive
300: Dead 75: Dead
- type: Stamina - type: Stamina
excess: 300 excess: 300
- type: SlowOnDamage - type: SlowOnDamage
@@ -175,15 +175,16 @@
- type: MobThresholds - type: MobThresholds
thresholds: thresholds:
0: Alive 0: Alive
200: Dead 150: Dead
- type: MeleeWeapon
damage:
groups:
Brute: 5
- type: Stamina - type: Stamina
excess: 200 excess: 200
- type: MovementSpeedModifier - type: MovementSpeedModifier
baseWalkSpeed : 3.0 baseWalkSpeed : 3.0
baseSprintSpeed : 5.5 baseSprintSpeed : 5.5
- type: SlowOnDamage
speedModifierThresholds:
150: 0.7
- type: Fixtures - type: Fixtures
fixtures: fixtures:
- shape: - shape:
@@ -214,7 +215,7 @@
- type: MobThresholds - type: MobThresholds
thresholds: thresholds:
0: Alive 0: Alive
1500: Dead 300: Dead
- type: Stamina - type: Stamina
excess: 1500 excess: 1500
- type: MovementSpeedModifier - type: MovementSpeedModifier
@@ -224,7 +225,7 @@
hidden: true hidden: true
damage: damage:
groups: groups:
Brute: 40 Brute: 20
- type: SlowOnDamage - type: SlowOnDamage
speedModifierThresholds: speedModifierThresholds:
1000: 0.7 1000: 0.7
@@ -258,7 +259,7 @@
- type: MobThresholds - type: MobThresholds
thresholds: thresholds:
0: Alive 0: Alive
550: Dead 200: Dead
- type: Stamina - type: Stamina
excess: 550 excess: 550
- type: MovementSpeedModifier - type: MovementSpeedModifier
@@ -268,7 +269,7 @@
hidden: true hidden: true
damage: damage:
groups: groups:
Brute: 20 Brute: 10
- type: SlowOnDamage - type: SlowOnDamage
speedModifierThresholds: speedModifierThresholds:
450: 0.7 450: 0.7
@@ -302,7 +303,7 @@
- type: MobThresholds - type: MobThresholds
thresholds: thresholds:
0: Alive 0: Alive
250: Dead 50: Dead
- type: Stamina - type: Stamina
excess: 250 excess: 250
- type: MovementSpeedModifier - type: MovementSpeedModifier
@@ -312,15 +313,12 @@
hidden: true hidden: true
damage: damage:
groups: groups:
Brute: 8 Brute: 3
- type: SlowOnDamage
speedModifierThresholds:
200: 0.7
- type: Fixtures - type: Fixtures
fixtures: fixtures:
- shape: - shape:
!type:PhysShapeCircle !type:PhysShapeCircle
radius: 0.45 radius: 0.35
density: 235 density: 235
mask: mask:
- MobMask - MobMask
@@ -356,7 +354,7 @@
- type: MobThresholds - type: MobThresholds
thresholds: thresholds:
0: Alive 0: Alive
300: Dead 75: Dead
- type: Stamina - type: Stamina
excess: 300 excess: 300
- type: SlowOnDamage - type: SlowOnDamage

View File

@@ -0,0 +1,49 @@
- type: entity
id: XenoWardingTower
name: Xeno warding tower
description: a
placement:
mode: SnapgridCenter
snap:
- Wall
components:
- type: RangedDamageSound
soundGroups:
Brute:
collection:
MeatBulletImpact
soundTypes:
Heat:
collection:
MeatLaserImpact
- type: InteractionOutline
- type: Sprite
netsync: false
sprite: Structures/Specific/xeno_building.rsi
layers:
- state: wardingtower
- state: wardingtower-unshaded
shader: unshaded
- type: Damageable
damageContainer: Inorganic
damageModifierSet: Metallic
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
- shape:
!type:PhysShapeAabb
bounds: "-0.5,-0.5,0.5,0.5"
mask:
- FullTileMask
layer:
- WallLayer
density: 1000
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 50
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]

View File

@@ -11,6 +11,7 @@
- state: basalt1 - state: basalt1
shader: unshaded shader: unshaded
drawdepth: LowFloors drawdepth: LowFloors
- type: SyncSprite
- type: RequiresTile - type: RequiresTile
- type: Transform - type: Transform
anchored: true anchored: true

View File

@@ -0,0 +1,39 @@
- type: entity
id: FloorWaterEntity
name: water
placement:
mode: SnapgridCenter
snap:
- Wall
components:
- type: StepTrigger
requiredTriggeredSpeed: 0
intersectRatio: 0.1
- type: Transform
anchored: true
- type: SyncSprite
- type: Sprite
sprite: Tiles/Planet/water.rsi
netsync: false
drawdepth: BelowFloor
layers:
- state: shoreline_water
- type: SlowContacts
walkSpeedModifier: 0.5
sprintSpeedModifier: 0.5
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
- shape:
!type:PhysShapeAabb
bounds: "-0.5,-0.5,0.5,0.5"
layer:
- SlipLayer
mask:
- ItemMask
density: 1000
hard: false
- type: FootstepModifier
footstepSoundCollection:
collection: FootstepWater

View File

@@ -14,7 +14,7 @@
scrolling: "0.1, -0.05" scrolling: "0.1, -0.05"
- type: parallax - type: parallax
id: Grass id: Dirt
layers: layers:
- texture: - texture:
!type:ImageParallaxTextureSource !type:ImageParallaxTextureSource
@@ -23,6 +23,16 @@
scale: "1, 1" scale: "1, 1"
shader: "" shader: ""
- type: parallax
id: Grass
layers:
- texture:
!type:ImageParallaxTextureSource
path: /Textures/Tiles/Planet/Grass/grass.png
slowness: 0
scale: "1, 1"
shader: ""
- type: parallax - type: parallax
id: Snow id: Snow
layers: layers:

View File

@@ -0,0 +1,324 @@
# Rooms
# Large
# - 17x5
- type: dungeonRoom
id: Science17x5a
size: 17,5
atlas: /Maps/Dungeon/experiment.yml
offset: 0,0
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science17x5b
size: 17,5
atlas: /Maps/Dungeon/experiment.yml
offset: 18,0
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science17x5c
size: 17,5
atlas: /Maps/Dungeon/experiment.yml
offset: 36,0
tags:
- SalvageExperiment
# - 7x7
- type: dungeonRoom
id: Science7x7a
size: 7,7
atlas: /Maps/Dungeon/experiment.yml
offset: 0,42
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x7b
size: 7,7
atlas: /Maps/Dungeon/experiment.yml
offset: 8,42
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x7c
size: 7,7
atlas: /Maps/Dungeon/experiment.yml
offset: 16,42
tags:
- SalvageExperiment
# Medium
# - 11x5
- type: dungeonRoom
id: Science11x5a
size: 11,5
atlas: /Maps/Dungeon/experiment.yml
offset: 0,6
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science11x5b
size: 11,5
atlas: /Maps/Dungeon/experiment.yml
offset: 12,6
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science11x5c
size: 11,5
atlas: /Maps/Dungeon/experiment.yml
offset: 24,6
tags:
- SalvageExperiment
# - 7x5
- type: dungeonRoom
id: Science7x5a
size: 7,5
atlas: /Maps/Dungeon/experiment.yml
offset: 0,12
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x5b
size: 7,5
atlas: /Maps/Dungeon/experiment.yml
offset: 8,12
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x5c
size: 7,5
atlas: /Maps/Dungeon/experiment.yml
offset: 16,12
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x5d
size: 7,5
atlas: /Maps/Dungeon/experiment.yml
offset: 24,12
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x5e
size: 7,5
atlas: /Maps/Dungeon/experiment.yml
offset: 32,12
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x5f
size: 7,5
atlas: /Maps/Dungeon/experiment.yml
offset: 40,12
tags:
- SalvageExperiment
# - 13x3
- type: dungeonRoom
id: Science13x3a
size: 13,3
atlas: /Maps/Dungeon/experiment.yml
offset: 0,30
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science13x3b
size: 13,3
atlas: /Maps/Dungeon/experiment.yml
offset: 14,30
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science13x3c
size: 13,3
atlas: /Maps/Dungeon/experiment.yml
offset: 28,30
tags:
- SalvageExperiment
# - 11x3
- type: dungeonRoom
id: Science11x3a
size: 11,3
atlas: /Maps/Dungeon/experiment.yml
offset: 0,34
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science11x3b
size: 11,3
atlas: /Maps/Dungeon/experiment.yml
offset: 12,34
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science11x3c
size: 11,3
atlas: /Maps/Dungeon/experiment.yml
offset: 24,34
tags:
- SalvageExperiment
# - 7x3
- type: dungeonRoom
id: Science7x3a
size: 7,3
atlas: /Maps/Dungeon/experiment.yml
offset: 0,38
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x3b
size: 7,3
atlas: /Maps/Dungeon/experiment.yml
offset: 8,38
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x3c
size: 7,3
atlas: /Maps/Dungeon/experiment.yml
offset: 16,38
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x3d
size: 7,3
atlas: /Maps/Dungeon/experiment.yml
offset: 24,38
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x3e
size: 7,3
atlas: /Maps/Dungeon/experiment.yml
offset: 32,38
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science7x3f
size: 7,3
atlas: /Maps/Dungeon/experiment.yml
offset: 40,38
tags:
- SalvageExperiment
# Small
# - 5x5
- type: dungeonRoom
id: Science5x5a
size: 5,5
atlas: /Maps/Dungeon/experiment.yml
offset: 0,18
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science5x5b
size: 5,5
atlas: /Maps/Dungeon/experiment.yml
offset: 6,18
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science5x5c
size: 5,5
atlas: /Maps/Dungeon/experiment.yml
offset: 12,18
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science5x5d
size: 5,5
atlas: /Maps/Dungeon/experiment.yml
offset: 18,18
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science5x5e
size: 5,5
atlas: /Maps/Dungeon/experiment.yml
offset: 24,18
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science5x5f
size: 5,5
atlas: /Maps/Dungeon/experiment.yml
offset: 30,18
tags:
- SalvageExperiment
# - 3x5
- type: dungeonRoom
id: Science3x5a
size: 3,5
atlas: /Maps/Dungeon/experiment.yml
offset: 0,24
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science3x5b
size: 3,5
atlas: /Maps/Dungeon/experiment.yml
offset: 4,24
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science3x5c
size: 3,5
atlas: /Maps/Dungeon/experiment.yml
offset: 8,24
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science3x5d
size: 3,5
atlas: /Maps/Dungeon/experiment.yml
offset: 12,24
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science3x5e
size: 3,5
atlas: /Maps/Dungeon/experiment.yml
offset: 16,24
tags:
- SalvageExperiment
- type: dungeonRoom
id: Science3x5f
size: 3,5
atlas: /Maps/Dungeon/experiment.yml
offset: 20,24
tags:
- SalvageExperiment

View File

@@ -0,0 +1,58 @@
- type: dungeonConfig
id: Experiment
generator: !type:PrefabDunGen
roomWhitelist:
- SalvageExperiment
presets:
- Cross
postGeneration:
- !type:MiddleConnectionPostGen
overlapCount: 3
count: 3
entities:
- CableApcExtension
- AirlockGlass
edgeEntities:
- Grille
- Window
- !type:MiddleConnectionPostGen
count: 1
entities:
- CableApcExtension
- AirlockGlass
- !type:EntrancePostGen
count: 2
entities:
- AirlockGlass
- !type:InternalWindowPostGen
entities:
- Grille
- Window
- !type:ExternalWindowPostGen
entities:
- Grille
- Window
- !type:WallMountPostGen
spawns:
# Posters
- id: RandomPosterLegit
orGroup: content
- id: ExtinguisherCabinetFilled
prob: 0.2
orGroup: content
- id: RandomPainting
prob: 0.05
orGroup: content
- id: Intercom
prob: 0.1
orGroup: content
- !type:BoundaryWallPostGen
tile: FloorSteel
wall: WallSolid
cornerWall: WallReinforced

Some files were not shown because too many files have changed in this diff Show More