diff --git a/Content.Server/Points/PointSystem.cs b/Content.Server/Points/PointSystem.cs
index b5f94d097ed..ba1d06b6451 100644
--- a/Content.Server/Points/PointSystem.cs
+++ b/Content.Server/Points/PointSystem.cs
@@ -1,4 +1,5 @@
using System.Linq;
+using Content.Server._Miracle.GameRules;
using Content.Shared.FixedPoint;
using Content.Shared.Points;
using JetBrains.Annotations;
@@ -86,4 +87,81 @@ public override FormattedMessage GetScoreboard(EntityUid uid, PointManagerCompon
return msg;
}
+
+ // WD EDIT START. Violence gamemode team points
+
+ ///
+ /// Adds the specified point value to a player.
+ ///
+ [PublicAPI]
+ public void AdjustTeamPointValue(ushort team, FixedPoint2 value, EntityUid uid, PointManagerComponent? component)
+ {
+ if (!Resolve(uid, ref component))
+ return;
+
+ if (!component.TeamPoints.TryGetValue(team, out var current))
+ current = FixedPoint2.Zero;
+
+ SetTeamPointValue(team, current + value, uid, component);
+ }
+
+ ///
+ /// Sets the amount of points for a player
+ ///
+ [PublicAPI]
+ public void SetTeamPointValue(ushort team, FixedPoint2 value, EntityUid uid, PointManagerComponent? component)
+ {
+ if (!Resolve(uid, ref component))
+ return;
+
+ if (component.TeamPoints.TryGetValue(team, out var current) && current == value)
+ return;
+
+ component.TeamPoints[team] = value;
+ component.TeamScoreboard = GetTeamScoreboard(uid, component);
+ Dirty(uid, component);
+
+ var ev = new TeamPointChangedEvent(team, value);
+ RaiseLocalEvent(uid, ref ev, true);
+ }
+
+ ///
+ /// Gets the amount of points for a given player
+ ///
+ [PublicAPI]
+ public FixedPoint2 GetTeamPointValue(ushort team, EntityUid uid, PointManagerComponent? component)
+ {
+ if (!Resolve(uid, ref component))
+ return FixedPoint2.Zero;
+
+ return component.TeamPoints.TryGetValue(team, out var value)
+ ? value
+ : FixedPoint2.Zero;
+ }
+
+ // Ignore this method, I will finish it later myself.
+ public override FormattedMessage GetTeamScoreboard(EntityUid uid, PointManagerComponent? component = null)
+ {
+ var msg = new FormattedMessage();
+
+ if (!Resolve(uid, ref component))
+ return msg;
+
+ var orderedPlayers = component.Points.OrderByDescending(p => p.Value).ToList();
+ var place = 1;
+ foreach (var (id, points) in orderedPlayers)
+ {
+ if (!_player.TryGetPlayerData(id, out var data))
+ continue;
+
+ msg.AddMarkup(Loc.GetString("point-scoreboard-list",
+ ("place", place),
+ ("name", data.UserName),
+ ("points", points.Int())));
+ msg.PushNewline();
+ place++;
+ }
+
+ return msg;
+ }
}
diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.Map.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.Map.cs
index 120e04eeb08..3f9f690dd2a 100644
--- a/Content.Server/Polymorph/Systems/PolymorphSystem.Map.cs
+++ b/Content.Server/Polymorph/Systems/PolymorphSystem.Map.cs
@@ -24,9 +24,9 @@ private void OnRoundRestart(RoundRestartCleanupEvent _)
///
/// Used internally to ensure a paused map that is
- /// stores polymorphed entities.
+ /// stores polymorphed entities. WD EDIT to make it public
///
- private void EnsurePausedMap()
+ public void EnsurePausedMap()
{
if (PausedMap != null && Exists(PausedMap))
return;
diff --git a/Content.Server/Spawners/Components/SpawnPointComponent.cs b/Content.Server/Spawners/Components/SpawnPointComponent.cs
index 5a86175a1d2..afa3ee2b224 100644
--- a/Content.Server/Spawners/Components/SpawnPointComponent.cs
+++ b/Content.Server/Spawners/Components/SpawnPointComponent.cs
@@ -16,6 +16,13 @@ public sealed partial class SpawnPointComponent : Component
[DataField("spawn_type")]
public SpawnPointType SpawnType { get; private set; } = SpawnPointType.Unset;
+ ///
+ /// WD EDIT. This is needed for Violence gamemode for team spawners.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("teamId")]
+ public ushort? TeamId = null;
+
public JobPrototype? Job => string.IsNullOrEmpty(_jobId) ? null : _prototypeManager.Index(_jobId);
public override string ToString()
diff --git a/Content.Server/Spawners/EntitySystems/SpawnPointSystem.cs b/Content.Server/Spawners/EntitySystems/SpawnPointSystem.cs
index b98e04844b9..221ff56cea7 100644
--- a/Content.Server/Spawners/EntitySystems/SpawnPointSystem.cs
+++ b/Content.Server/Spawners/EntitySystems/SpawnPointSystem.cs
@@ -34,14 +34,16 @@ private void OnPlayerSpawning(PlayerSpawningEvent args)
if (_gameTicker.RunLevel == GameRunLevel.InRound && spawnPoint.SpawnType == SpawnPointType.LateJoin)
{
- possiblePositions.Add(xform.Coordinates);
+ if (args.Team == spawnPoint.TeamId) // WD EDIT. Violence gamemode spawns needed here
+ possiblePositions.Add(xform.Coordinates);
}
if (_gameTicker.RunLevel != GameRunLevel.InRound &&
spawnPoint.SpawnType == SpawnPointType.Job &&
(args.Job == null || spawnPoint.Job?.ID == args.Job.Prototype))
{
- possiblePositions.Add(xform.Coordinates);
+ if (args.Team == spawnPoint.TeamId) // WD EDIT.
+ possiblePositions.Add(xform.Coordinates);
}
}
diff --git a/Content.Server/Station/Systems/StationSpawningSystem.cs b/Content.Server/Station/Systems/StationSpawningSystem.cs
index 557d0d63b68..71fbe350c27 100644
--- a/Content.Server/Station/Systems/StationSpawningSystem.cs
+++ b/Content.Server/Station/Systems/StationSpawningSystem.cs
@@ -67,23 +67,24 @@ public override void Initialize()
}
///
- /// Attempts to spawn a player character onto the given station.
+ /// Attempts to spawn a player character onto the given station. WD EDIT
///
/// Station to spawn onto.
/// The job to assign, if any.
/// The character profile to use, if any.
/// Resolve pattern, the station spawning component for the station.
+ /// Player's team for Violence GameRule. WD EDIT;
/// The resulting player character, if any.
/// Thrown when the given station is not a station.
///
/// This only spawns the character, and does none of the mind-related setup you'd need for it to be playable.
///
- public EntityUid? SpawnPlayerCharacterOnStation(EntityUid? station, JobComponent? job, HumanoidCharacterProfile? profile, StationSpawningComponent? stationSpawning = null)
+ public EntityUid? SpawnPlayerCharacterOnStation(EntityUid? station, JobComponent? job, HumanoidCharacterProfile? profile, StationSpawningComponent? stationSpawning = null, ushort? team = null)
{
if (station != null && !Resolve(station.Value, ref stationSpawning))
throw new ArgumentException("Tried to use a non-station entity as a station!", nameof(station));
- var ev = new PlayerSpawningEvent(job, profile, station);
+ var ev = new PlayerSpawningEvent(job, profile, station, team);
if (station != null && profile != null)
{
@@ -326,10 +327,17 @@ public sealed class PlayerSpawningEvent : EntityEventArgs
///
public readonly EntityUid? Station;
- public PlayerSpawningEvent(JobComponent? job, HumanoidCharacterProfile? humanoidCharacterProfile, EntityUid? station)
+ ///
+ /// Player's team for Violence GameRule. WD EDIT
+ ///
+ public readonly ushort? Team;
+
+
+ public PlayerSpawningEvent(JobComponent? job, HumanoidCharacterProfile? humanoidCharacterProfile, EntityUid? station, ushort? team)
{
Job = job;
HumanoidCharacterProfile = humanoidCharacterProfile;
Station = station;
+ Team = team; //WD EDIT
}
}
diff --git a/Content.Server/_Miracle/Components/ViolenceParticipatorComponent.cs b/Content.Server/_Miracle/Components/ViolenceParticipatorComponent.cs
new file mode 100644
index 00000000000..3e5434812a8
--- /dev/null
+++ b/Content.Server/_Miracle/Components/ViolenceParticipatorComponent.cs
@@ -0,0 +1,14 @@
+namespace Content.Server._Miracle.Components;
+
+///
+/// This is used for...
+///
+[RegisterComponent]
+public sealed partial class ViolenceParticipatorComponent : Component
+{
+ ///
+ /// List of factions in this gamemode.
+ ///
+ [DataField]
+ public EntityUid? MatchUid { get; private set; } = null;
+}
diff --git a/Content.Server/_Miracle/GameRules/Violence/SwitchTeamCommand.cs b/Content.Server/_Miracle/GameRules/Violence/SwitchTeamCommand.cs
new file mode 100644
index 00000000000..a3e430fc75e
--- /dev/null
+++ b/Content.Server/_Miracle/GameRules/Violence/SwitchTeamCommand.cs
@@ -0,0 +1,46 @@
+using Content.Server.Administration;
+using Content.Shared.Administration;
+using Robust.Shared.Console;
+using Robust.Shared.Network;
+
+// TODO: test permissions
+namespace Content.Server._Miracle.GameRules.Violence;
+
+[AdminCommand(AdminFlags.Admin)]
+internal class SwitchTeamCommand : IConsoleCommand
+{
+ [Dependency] private readonly IPlayerLocator _locator = default!;
+
+ public string Command => "switchteam";
+ public string Description => "Switches the player's team.";
+ public string Help => "switchteam ";
+
+ public async void Execute(IConsoleShell shell, string argStr, string[] args)
+ {
+ if (args.Length != 2)
+ {
+ shell.WriteLine("Expected exactly 2 arguments.");
+ return;
+ }
+
+ var target = args[0];
+ var located = await _locator.LookupIdByNameOrIdAsync(target);
+ var player = shell.Player;
+
+ if (player == null)
+ {
+ shell.WriteLine("Player not found.");
+ return;
+ }
+
+ if (!ushort.TryParse(args[1], out var newTeamId))
+ {
+ shell.WriteLine($"Invalid team ID: {args[1]}");
+ return;
+ }
+
+ var violenceRuleSystem = IoCManager.Resolve().GetEntitySystem();
+ violenceRuleSystem.SwitchTeam(player.UserId, newTeamId);
+ }
+}
+
diff --git a/Content.Server/_Miracle/GameRules/Violence/ViolenceRuleComponent.cs b/Content.Server/_Miracle/GameRules/Violence/ViolenceRuleComponent.cs
new file mode 100644
index 00000000000..1aeb83b30e6
--- /dev/null
+++ b/Content.Server/_Miracle/GameRules/Violence/ViolenceRuleComponent.cs
@@ -0,0 +1,180 @@
+using Content.Shared.FixedPoint;
+using Robust.Shared.Map;
+using Robust.Shared.Network;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Server._Miracle.GameRules.Violence;
+
+[RegisterComponent]
+[Access(typeof(ViolenceRuleSystem))]
+public sealed partial class ViolenceRuleComponent : Component
+{
+ ///
+ /// Min players needed for Violence round to start.
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public int MinPlayers = 2;
+
+ ///
+ /// Max players needed for Violence round.
+ ///
+ [DataField("maxPlayers"), ViewVariables(VVAccess.ReadWrite)]
+ public Dictionary MaxPlayers = new Dictionary();
+
+ ///
+ /// How long until the round restarts
+ ///
+ [DataField("restartDelay"), ViewVariables(VVAccess.ReadWrite)]
+ public TimeSpan RestartDelay = TimeSpan.FromSeconds(10f);
+
+ ///
+ /// Time until automatic match end.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan? MatchDuration = null;
+
+ ///
+ /// Time until automatic match end.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan? MatchStartTime = null;
+
+ ///
+ /// List of teams in this gamemode.
+ ///
+ [DataField("teams")]
+ public IReadOnlyList Teams { get; private set; } = Array.Empty();
+
+ ///
+ /// List of scores in this gamemode.
+ ///
+ [DataField("teamScores"), ViewVariables(VVAccess.ReadWrite)]
+ public Dictionary TeamScores { get; private set; } = new Dictionary();
+
+ List kd = new List(new int[2]);
+ ///
+ /// Stores number of kills and deaths for each player. Indexes: 0 for kills, 1 for assists, 2 for deaths.
+ ///
+ [DataField("killsDeaths"), ViewVariables(VVAccess.ReadWrite)]
+ public Dictionary> KillDeaths { get; private set; } = new Dictionary>();
+
+ ///
+ /// Stored, for some reason.
+ ///
+ [DataField("matchVictor"), ViewVariables(VVAccess.ReadWrite)]
+ public ushort? MatchVictor;
+
+ ///
+ /// The number of points a player has to get to win.
+ ///
+ [DataField("pointCap"), ViewVariables(VVAccess.ReadWrite)]
+ public FixedPoint2 PointCap = 5;
+
+ ///
+ /// Time when current round ends.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan RoundEndTime = TimeSpan.FromMinutes(5);
+
+ ///
+ /// Time between final kill of the round and actual round end.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan RoundEndDelay = TimeSpan.FromSeconds(10);
+
+ ///
+ /// Time when new round starts.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan RoundStartTime = TimeSpan.Zero;
+
+ ///
+ /// Time between player's spawns and round start.
+ ///
+ [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan RoundStartDelay = TimeSpan.FromSeconds(10);
+
+ ///
+ /// The duration of a round.
+ ///
+ [DataField("roundDuration", customTypeSerializer: typeof(TimeOffsetSerializer))]
+ public TimeSpan RoundDuration = TimeSpan.FromMinutes(5);
+
+ ///
+ /// Dictionary of a players and their teams
+ ///
+ [DataField("teamMembers"), ViewVariables(VVAccess.ReadWrite)]
+ public Dictionary TeamMembers { get; private set; } = new Dictionary();
+
+ ///
+ /// Dictionary of a players and their money.
+ ///
+ [DataField("money"), ViewVariables(VVAccess.ReadWrite)]
+ public Dictionary Money { get; private set; } = new Dictionary();
+
+ ///
+ /// Dictionary of teams and dictionaries of items and their prices. Shop[team][item].Price = price of said item. Shop[team][item].Slot - slot of the said item. Item itself is prototypeID
+ ///
+ [DataField("shop"), ViewVariables(VVAccess.ReadWrite)]
+ public Dictionary> Shop { get; private set; } = new Dictionary>();
+
+ ///
+ /// Dictionary of a players and lists of their equipment.
+ ///
+ [DataField("savedEquip"), ViewVariables(VVAccess.ReadWrite)]
+ public Dictionary> SavedEquip { get; private set; } = new Dictionary>();
+
+ ///
+ /// This tries to save the slots of player's equip from the last round.
+ ///
+ [DataField("equipSlots"), ViewVariables(VVAccess.ReadWrite)]
+ public Dictionary EquipSlots { get; private set; } = new Dictionary();
+
+ ///
+ /// Reward for remaining alive at the end of the round.
+ ///
+ [DataField("aliveReward"), ViewVariables(VVAccess.ReadWrite)]
+ public int AliveReward { get; private set; } = 300;
+
+ ///
+ /// Reward for a kill.
+ ///
+ [DataField("killReward"), ViewVariables(VVAccess.ReadWrite)]
+ public int KillReward { get; private set; } = 300;
+
+ ///
+ /// Reward for an assist.
+ ///
+ [DataField("assistReward"), ViewVariables(VVAccess.ReadWrite)]
+ public int AssistReward { get; private set; } = 100;
+
+
+ ///
+ /// Penalty for suicide or being thrown in lava or something.
+ ///
+ [DataField("skillIssuePenalty"), ViewVariables(VVAccess.ReadWrite)]
+ public int SkillIssuePenalty { get; private set; } = 300;
+
+
+ ///
+ /// Pool of maps for this set of teams
+ ///
+ [DataField("mapPool"), ViewVariables(VVAccess.ReadWrite)]
+ public string MapPool;
+
+ ///
+ /// EntityUid of current map.
+ ///
+ [DataField, ViewVariables(VVAccess.ReadWrite)]
+ public MapId? CurrentMap = null;
+
+ [DataField("roundState"), ViewVariables(VVAccess.ReadWrite)]
+ public RoundState RoundState { get; set; } = RoundState.NotInProgress;
+}
+
+public enum RoundState
+{
+ Starting,
+ InProgress,
+ NotInProgress
+}
diff --git a/Content.Server/_Miracle/GameRules/Violence/ViolenceRuleSystem.cs b/Content.Server/_Miracle/GameRules/Violence/ViolenceRuleSystem.cs
new file mode 100644
index 00000000000..956e9f735dc
--- /dev/null
+++ b/Content.Server/_Miracle/GameRules/Violence/ViolenceRuleSystem.cs
@@ -0,0 +1,813 @@
+using System.Linq;
+using Content.Server.GameTicking;
+using Content.Server.GameTicking.Rules;
+using Content.Server.GameTicking.Rules.Components;
+using Content.Server.Inventory;
+using Content.Server.RoundEnd;
+using Content.Server.Station.Systems;
+using Content.Server.KillTracking;
+using Content.Server.Maps;
+using Content.Server.Mind;
+using Content.Server.Points;
+using Content.Server.Polymorph.Systems;
+using Content.Shared.Hands.Components;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Inventory;
+using Content.Shared.Mind;
+using Content.Shared.Mobs;
+using Content.Shared.Mobs.Components;
+using Content.Shared.Points;
+using Robust.Server.GameObjects;
+using Robust.Server.Player;
+using Robust.Shared.Utility;
+using Robust.Shared.Console;
+using Robust.Shared.Map;
+using Robust.Shared.Network;
+using Robust.Shared.Player;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
+using Robust.Shared.Timing;
+
+namespace Content.Server._Miracle.GameRules.Violence;
+
+// TODO: respawns may suck
+// TODO: ViolencePreset, that sets MapPool, teams, Shop, rewards, StartingGear, PointCap, RoundDuration and possibly more!
+// TODO: recheck match flow and round flow
+// TODO: test buying equipment
+// TODO: prototypes of gameRule, uplink? and startingGear, gameMapPool, the map itself
+// TODO: make a menu to join the round, switch teams, leave the round, get scoreboard - мб сделает валтос
+// TODO: localize kill callouts
+
+public sealed class ViolenceRuleSystem : GameRuleSystem
+{
+ [Dependency] private readonly RoundEndSystem _roundEnd = default!;
+ [Dependency] private readonly MindSystem _mind = default!;
+ [Dependency] private readonly PointSystem _point = default!;
+ [Dependency] private readonly RespawnRuleSystem _respawn = default!;
+ [Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
+ [Dependency] private readonly IRobustRandom _robustRandom = default!;
+ [Dependency] private readonly IConsoleHost _consoleHost = default!;
+ [Dependency] private readonly IMapManager _mapManager = default!;
+ [Dependency] private readonly ILogManager _logManager = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+ [Dependency] private readonly GameTicker _gameTicker = default!;
+ [Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly IPlayerManager _playerManager = default!;
+ [Dependency] private readonly PolymorphSystem _polymorphSystem = default!;
+ [Dependency] private readonly TransformSystem _transform = default!;
+ [Dependency] private readonly SharedHandsSystem _hands = default!;
+ [Dependency] private readonly ServerInventorySystem _inventory = default!;
+
+ private ISawmill _sawmill = default!;
+
+ private List _activeRules = new List();
+
+ private readonly string _defaultViolenceRule = "Violence";
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ _sawmill = _logManager.GetSawmill("violence");
+ //_sawmillReplays = _logManager.GetSawmill("violence.replays");
+
+ SubscribeLocalEvent(OnBeforeSpawn);
+ //SubscribeLocalEvent(OnPlayerSpawning);
+ SubscribeLocalEvent(OnSpawnComplete);
+ SubscribeLocalEvent(OnKillReported);
+ SubscribeLocalEvent(OnPointChanged);
+ //SubscribeLocalEvent(OnRoundEndTextAppend);
+ SubscribeLocalEvent(OnMobStateChanged);
+ }
+
+ protected override void ActiveTick(EntityUid uid, ViolenceRuleComponent comp, GameRuleComponent gameRule,
+ float frameTime)
+ {
+ base.ActiveTick(uid, comp, gameRule, frameTime);
+
+ switch (comp.RoundState)
+ {
+ case RoundState.InProgress:
+ if (_timing.CurTime >= comp.RoundEndTime)
+ {
+ EndRound(comp);
+ }
+ break;
+
+ case RoundState.Starting:
+
+ break;
+
+ case RoundState.NotInProgress:
+ if (_timing.CurTime >= comp.RoundStartTime)
+ {
+ StartRound(uid, comp);
+ }
+ break;
+ }
+ }
+
+ ///
+ /// This method handles roundstart player spawning. After roundstart, players will be spawned by RespawnRuleSystem.
+ ///
+ ///
+ private void OnBeforeSpawn(PlayerBeforeSpawnEvent ev)
+ {
+ /*
+ if (ev.LateJoin) // this will allow this gamerule to be added to usual rounds. maybe
+ return;
+ */
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var ruleComponent, out var tracker, out var point, out var rule))
+ {
+ if (!GameTicker.IsGameRuleActive(uid, rule))
+ continue;
+
+ var teamList = TeamsEligibleToJoin(ruleComponent);
+ if (teamList.Count == 0)
+ {
+ continue;
+ }
+
+ if (!ruleComponent.TeamMembers.TryGetValue(ev.Player.UserId, out var team))
+ {
+ ruleComponent.TeamMembers.Add(ev.Player.UserId, teamList[_robustRandom.Next(0, teamList.Count())]);
+ }
+
+ var newMind = _mind.CreateMind(ev.Player.UserId, ev.Profile.Name);
+ _mind.SetUserId(newMind, ev.Player.UserId);
+
+ var mobMaybe = _stationSpawning.SpawnPlayerCharacterOnStation(ev.Station, null, ev.Profile, null, team);
+ DebugTools.AssertNotNull(mobMaybe);
+ var mob = mobMaybe!.Value;
+
+ _mind.TransferTo(newMind, mob);
+ // Should get startingGear from the client here. Setting default startingGear if none or invalid is passed.
+ // Also different startingGear for different teams. A dictionary of teams and startingGear in ViolenceRuleComponent?
+ //SetOutfitCommand.SetOutfit(mob, ruleComponent.Gear, EntityManager);
+ EnsureComp(mob);
+ _respawn.AddToTracker(ev.Player.UserId, uid, tracker);
+
+ _point.EnsurePlayer(ev.Player.UserId, uid, point);
+
+ ev.Handled = true;
+ break;
+ }
+ }
+
+ ///
+ /// TODO: think about it. i think it is not needed. respawns are handled by StartRound anyway
+ ///
+ ///
+ private void OnSpawnComplete(PlayerSpawnCompleteEvent ev)
+ {
+ EnsureComp(ev.Mob);
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var violence, out var tracker, out var rule))
+ {
+ if (!GameTicker.IsGameRuleActive(uid, rule))
+ continue;
+
+ if (violence.TeamMembers.ContainsKey(ev.Player.UserId))
+ _respawn.AddToTracker(ev.Mob, uid, tracker);
+
+ if (violence.SavedEquip.TryGetValue(ev.Player.UserId, out var equip))
+ {
+ foreach (var equipId in equip)
+ {
+ if (violence.EquipSlots.TryGetValue(equipId, out var slot))
+ {
+ _transform.SetParent(equipId, ev.Station);
+ if (slot == "hand")
+ {
+ _hands.PickupOrDrop(ev.Mob, equipId);
+ }
+ else
+ {
+ _inventory.TryEquip(ev.Mob, equipId, slot);
+ }
+ }
+ }
+ equip.Clear();
+ }
+ }
+ }
+
+ private void OnMobStateChanged(MobStateChangedEvent ev)
+ {
+ if (ev.NewMobState != MobState.Dead)
+ return;
+
+ if (!TryComp(ev.Target, out var actor))
+ return;
+
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var ruleComponent, out _, out var rule))
+ {
+ if (!GameTicker.IsGameRuleActive(uid, rule))
+ continue;
+
+ var team = GetPlayersTeam(actor.PlayerSession.UserId, ruleComponent);
+ if (team == null)
+ continue;
+
+ var alive = GetAliveTeamMembersCount(team.Value, ruleComponent);
+ if (alive == 0)
+ {
+ if (CheckForRoundEnd(ruleComponent))
+ DoRoundEndBehavior(ruleComponent);
+ }
+ }
+ }
+
+ public bool StartRound(EntityUid uid, ViolenceRuleComponent comp)
+ {
+ if (comp.RoundState != RoundState.NotInProgress)
+ {
+ // probably assert here?
+ return false;
+ }
+
+ if (!comp.CurrentMap.HasValue)
+ {
+ comp.CurrentMap = _mapManager.CreateMap();
+
+ if (!comp.CurrentMap.HasValue)
+ return false; // i give up. or maybe load default map?
+
+ _mapManager.AddUninitializedMap(comp.CurrentMap.Value);
+
+ _prototypeManager.TryIndex(comp.MapPool, out var extractedMapPool);
+ if (extractedMapPool == null)
+ return false;
+
+ var mapPrototype = extractedMapPool.Maps.ElementAt(_robustRandom.Next(extractedMapPool.Maps.Count));
+ _prototypeManager.TryIndex(mapPrototype, out var map);
+
+ if (map != null)
+ {
+ _gameTicker.LoadGameMap(map, comp.CurrentMap.Value, null);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // TODO: recheck the rest of this method
+ // spawning players
+ foreach (var (playerId, teamId) in comp.TeamMembers)
+ {
+ _playerManager.TryGetSessionById(playerId, out var player);
+
+ if (player == null)
+ continue;
+
+ var profile = _gameTicker.GetPlayerProfile(player);
+
+ var newMind = _mind.CreateMind(playerId, profile.Name);
+ _mind.SetUserId(newMind, playerId);
+
+ if (!comp.CurrentMap.HasValue)
+ return false;
+ var station = _mapManager.GetMapEntityId(comp.CurrentMap.Value);
+
+ var mobMaybe = _stationSpawning.SpawnPlayerCharacterOnStation(station, null, profile, null, teamId);
+ DebugTools.AssertNotNull(mobMaybe);
+ var mob = mobMaybe!.Value;
+
+ _mind.TransferTo(newMind, mob);
+ // Should get startingGear from the client here. Setting default startingGear if none or invalid is passed.
+ // Also different startingGear for different teams. A dictionary of teams and startingGear in ViolenceRuleComponent?
+ //SetOutfitCommand.SetOutfit(mob, ruleComponent.Gear, EntityManager);
+ EnsureComp(mob);
+
+ if (TryComp(uid, out var tracker))
+ {
+ _respawn.AddToTracker(playerId, uid, tracker);
+ }
+ else
+ {
+ _respawn.AddToTracker(playerId, uid);
+ }
+
+ _point.EnsurePlayer(playerId, uid);
+
+ DebugTools.AssertNotNull(mobMaybe);
+ }
+
+ // Set round state and end time
+ comp.RoundState = RoundState.InProgress;
+ comp.RoundEndTime = _timing.CurTime + comp.RoundDuration;
+
+ return true;
+ }
+
+ public bool DoRoundEndBehavior(ViolenceRuleComponent comp)
+ {
+ // announce the winner
+ foreach (var (player, team) in comp.TeamMembers)
+ {
+ if (team != comp.MatchVictor)
+ continue;
+
+ if (!_playerManager.SessionsDict.TryGetValue(player, out var session))
+ continue;
+
+
+ _polymorphSystem.EnsurePausedMap();
+
+ if (session.AttachedEntity != null &&
+ TryComp(session.AttachedEntity, out var mobState) &&
+ mobState.CurrentState == MobState.Alive)
+ {
+ if (_polymorphSystem.PausedMap != null)
+ {
+ if (!comp.SavedEquip.ContainsKey(session.UserId))
+ {
+ comp.SavedEquip.Add(session.UserId, new List());
+ }
+
+ if (TryComp(session.AttachedEntity, out var hands))
+ {
+ foreach (var hand in _hands.EnumerateHeld(session.AttachedEntity.Value))
+ {
+ _hands.TryDrop(session.AttachedEntity.Value, hand, checkActionBlocker: false);
+ _transform.SetParent(hand, Transform(hand), _polymorphSystem.PausedMap.Value);
+ comp.SavedEquip[session.UserId].Add(hand);
+ comp.EquipSlots.Add(hand, "hand");
+ }
+ }
+ if (TryComp(session.AttachedEntity, out var inv))
+ {
+ var enumerator = new InventorySystem.InventorySlotEnumerator(inv);
+ while (enumerator.NextItem(out var item, out var slot))
+ {
+ _inventory.TryUnequip(session.AttachedEntity.Value, slot.Name, true, true);
+ _transform.SetParent(item, Transform(item), _polymorphSystem.PausedMap.Value);
+ comp.SavedEquip[session.UserId].Add(item);
+ comp.EquipSlots.Add(item, slot.Name);
+ }
+ }
+ }
+
+ // ummm TODO: test this
+ if (comp.Money.ContainsKey(session.UserId))
+ {
+ comp.Money[session.UserId] += comp.AliveReward;
+ }
+ else
+ {
+ comp.Money.TryAdd(session.UserId, comp.AliveReward);
+ }
+ }
+
+
+
+ }
+ // wait for comp.RoundEndDelay
+ return EndRound(comp);
+ }
+
+ public bool EndRound(ViolenceRuleComponent comp)
+ {
+ if (comp.RoundState == RoundState.NotInProgress)
+ {
+ // probably assert here?
+ return false;
+ }
+
+ comp.RoundState = RoundState.NotInProgress;
+
+ if (comp.CurrentMap.HasValue)
+ _mapManager.DeleteMap(comp.CurrentMap.Value);
+
+ comp.RoundStartTime = _timing.CurTime + comp.RoundStartDelay;
+ return true;
+ }
+
+
+ private void OnKillReported(ref KillReportedEvent ev)
+ {
+ ActorComponent? actor = null;
+ if (!Resolve(ev.Entity, ref actor, false))
+ return;
+
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var ruleComponent, out var point, out var rule))
+ {
+ if (!GameTicker.IsGameRuleActive(uid, rule))
+ continue;
+
+ var team = GetPlayersTeam(actor.PlayerSession.UserId, ruleComponent);
+ if (team == null)
+ continue;
+
+ if (!ruleComponent.KillDeaths.TryGetValue(actor.PlayerSession.UserId, out var targetKd))
+ {
+ targetKd = new List();
+ targetKd.Add(0);
+ targetKd.Add(0);
+ targetKd.Add(0);
+
+ ruleComponent.KillDeaths.Add(actor.PlayerSession.UserId, targetKd);
+ }
+ ruleComponent.KillDeaths[actor.PlayerSession.UserId][2]++;
+
+
+ // YOU SUICIDED OR GOT THROWN INTO LAVA!
+ // WHAT A GIANT FUCKING NERD! LAUGH NOW!
+ if (ev.Primary is not KillPlayerSource player)
+ {
+ if (!ruleComponent.Money.ContainsKey(actor.PlayerSession.UserId))
+ ruleComponent.Money.TryAdd(actor.PlayerSession.UserId, 0);
+
+ ruleComponent.Money[actor.PlayerSession.UserId] -= ruleComponent.SkillIssuePenalty;
+ continue;
+ }
+
+ if (ev.Primary is KillPlayerSource killer && ruleComponent.TeamMembers.TryGetValue(killer.PlayerId, out var killerTeam))
+ {
+ if (team != killerTeam)
+ {
+ if (!ruleComponent.KillDeaths.TryGetValue(killer.PlayerId, out var killerKd))
+ {
+ killerKd = new List();
+ killerKd.Add(0);
+ killerKd.Add(0);
+ killerKd.Add(0);
+
+ ruleComponent.KillDeaths.Add(actor.PlayerSession.UserId, killerKd);
+ }
+
+ ruleComponent.KillDeaths[killer.PlayerId][0]++;
+
+ if (!ruleComponent.Money.ContainsKey(killer.PlayerId))
+ ruleComponent.Money.TryAdd(killer.PlayerId, 0);
+
+ ruleComponent.Money[killer.PlayerId] += ruleComponent.KillReward;
+ }
+ }
+
+
+ if (ev.Assist is KillPlayerSource assist && ruleComponent.MatchVictor == null && ruleComponent.TeamMembers.TryGetValue(assist.PlayerId, out var assistTeam))
+ {
+ if (team != assistTeam)
+ {
+ if (!ruleComponent.KillDeaths.TryGetValue(assist.PlayerId, out var assistKd))
+ {
+ assistKd = new List();
+ assistKd.Add(0);
+ assistKd.Add(0);
+ assistKd.Add(0);
+
+ ruleComponent.KillDeaths.Add(actor.PlayerSession.UserId, assistKd);
+ }
+
+ ruleComponent.KillDeaths[assist.PlayerId][1]++;
+
+ if (!ruleComponent.Money.ContainsKey(assist.PlayerId))
+ ruleComponent.Money.TryAdd(assist.PlayerId, 0);
+
+ ruleComponent.Money[assist.PlayerId] += ruleComponent.AssistReward;
+ }
+ }
+
+ // I dont know if we will have reward spawns or any direct rewards for players
+ //var spawns = EntitySpawnCollection.GetSpawns(ruleComponent.RewardSpawns).Cast().ToList();
+ //EntityManager.SpawnEntities(Transform(ev.Entity).MapPosition, spawns);
+ }
+ }
+
+ private void OnPointChanged(EntityUid uid, ViolenceRuleComponent component, ref TeamPointChangedEvent args)
+ {
+ if (component.MatchVictor != null)
+ return;
+
+ if (args.Points <= component.PointCap)
+ return;
+
+ DoRoundEndBehavior(component);
+
+ component.MatchVictor = args.Team;
+ _gameTicker.EndGameRule(uid);
+ if (ActiveMatches() == 0)
+ {
+ // maybe wait a bit before ending the round?
+ _roundEnd.DoRoundEndBehavior(RoundEndBehavior.InstantEnd, TimeSpan.FromSeconds(10));
+ }
+ }
+
+ ///
+ /// I will rewrite this to not require component input if needed. In fact, TODO
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool TryBuyItem(NetUserId player, ViolenceRuleComponent comp, string item)
+ {
+ if (!comp.TeamMembers.TryGetValue(player, out var team))
+ return false;
+
+ if (!comp.Shop.TryGetValue(team, out var shop))
+ return false;
+
+ if (!shop.TryGetValue(item, out var listing))
+ return false;
+
+ if (!comp.Money.TryGetValue(player, out var money))
+ return false;
+
+
+ if (money >= listing.Price)
+ {
+ if (!_prototypeManager.TryIndex(item, out var proto))
+ return false;
+
+ comp.Money[player] -= listing.Price;
+
+ if (!_playerManager.GetSessionById(player).AttachedEntity.HasValue)
+ {
+
+ }
+
+ _polymorphSystem.EnsurePausedMap();
+ var equip = EntityManager.SpawnEntity(item, new EntityCoordinates(_polymorphSystem.PausedMap!.Value, 0, 0));
+
+ if (!comp.SavedEquip.ContainsKey(player))
+ {
+ comp.SavedEquip.Add(player, new List());
+ }
+ comp.SavedEquip[player].Add(equip);
+ comp.EquipSlots.Add(equip, listing.Slot);
+ }
+
+ return false;
+ }
+
+ private int ActiveMatches()
+ {
+ int count = 0;
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var violence, out var rule))
+ {
+ if (GameTicker.IsGameRuleActive(uid, rule))
+ count++;
+ }
+
+ return count;
+ }
+
+ ///
+ /// Tries to join the round
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool JoinRound(NetUserId player, ViolenceRuleComponent comp, ushort? preferredTeam = null, bool anyTeam = false)
+ {
+ // Check if the player is already a member of a team
+ if (comp.TeamMembers.ContainsKey(player))
+ {
+ return false;
+ }
+
+ var eligibleTeams = TeamsEligibleToJoin(comp);
+ // If there are no eligible teams, return false
+ if (eligibleTeams.Count == 0)
+ {
+ return false;
+ }
+
+ // If a team is specified, check if it's eligible for joining
+ if (preferredTeam.HasValue)
+ {
+ if (eligibleTeams.Contains(preferredTeam.Value))
+ {
+ comp.TeamMembers.Add(player, preferredTeam.Value);
+ return true;
+ }
+
+ if (!anyTeam)
+ return false;
+ }
+
+ // Randomly select a team from the eligible teams and add the player to it
+ var selectedTeam = eligibleTeams[_robustRandom.Next(0, eligibleTeams.Count)];
+ comp.TeamMembers.Add(player, selectedTeam);
+
+ return true;
+ }
+
+ public bool LeaveRound(NetUserId player, ViolenceRuleComponent comp)
+ {
+ if (!comp.TeamMembers.ContainsKey(player))
+ return false;
+
+ comp.TeamMembers.Remove(player);
+ return true;
+ }
+
+ ///
+ /// Get a player's team from EntityUid and ViolenceRuleComponent
+ ///
+ ///
+ ///
+ ///
+ private ushort? GetPlayersTeam(NetUserId userId, ViolenceRuleComponent comp)
+ {
+ if (!comp.TeamMembers.TryGetValue(userId, out var team))
+ return null;
+
+ return team;
+ }
+
+ public int GetAliveTeamMembersCount(ushort teamId, ViolenceRuleComponent comp)
+ {
+ var alive = 0;
+
+ foreach (var (player, team) in comp.TeamMembers)
+ {
+ if (team == teamId)
+ {
+ var mind = _mind.GetMind(player);
+ if (mind == null || TryComp(mind, out var mindComponent) || mindComponent == null)
+ continue;
+
+ if (mindComponent.OwnedEntity == null)
+ continue;
+
+ if (!TryComp(mindComponent.OwnedEntity.Value, out var mobStateComponent))
+ continue;
+
+ if (mobStateComponent.CurrentState != MobState.Alive)
+ continue;
+
+ alive++;
+ }
+ }
+
+ return alive;
+ }
+
+ ///
+ /// Round ends only if players of one single team are alive.
+ ///
+ ///
+ ///
+ public bool CheckForRoundEnd(ViolenceRuleComponent comp)
+ {
+ if (comp.RoundState != RoundState.InProgress)
+ return false;
+
+ var aliveTeams = new List();
+
+ foreach (var team in comp.Teams)
+ {
+ if (GetAliveTeamMembersCount(team, comp) > 0)
+ {
+ aliveTeams.Add(team);
+ }
+ }
+
+ if (aliveTeams.Count == 1)
+ {
+ comp.MatchVictor = aliveTeams[0];
+ return true;
+ }
+
+ if (aliveTeams.Count == 0)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ // Do we even need that?
+ public void SwitchTeam(NetUserId playerId, ushort newTeamId)
+ {
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var ruleComponent, out var rule))
+ {
+ if (!GameTicker.IsGameRuleActive(uid, rule))
+ continue;
+
+ if (!ruleComponent.TeamMembers.ContainsKey(playerId))
+ continue;
+
+ if (!ruleComponent.Teams.Contains(newTeamId))
+ return;
+
+ if (ruleComponent.TeamMembers[playerId] == newTeamId)
+ return;
+
+ var currentTeamId = ruleComponent.TeamMembers[playerId];
+ var currentTeamCount = ruleComponent.TeamMembers.Values.Count(teamId => teamId == currentTeamId);
+ var newTeamCount = ruleComponent.TeamMembers.Values.Count(teamId => teamId == newTeamId);
+
+ if (newTeamCount >= currentTeamCount * 1.2)
+ return;
+
+ ruleComponent.TeamMembers[playerId] = newTeamId;
+
+ // TODO: maybe clear equipment and money?
+ }
+ }
+
+ ///
+ /// Create new instance of the rule entity. TODO: limit the number of these
+ ///
+ ///
+ ///
+ public ViolenceRuleComponent? CreateNewInstance(string? ruleId)
+ {
+ if (ruleId == null)
+ ruleId = _defaultViolenceRule;
+
+ var ruleEntity = _gameTicker.AddGameRule(ruleId);
+
+ if (!TryComp(ruleEntity, out var comp))
+ {
+ EntityManager.DeleteEntity(ruleEntity);
+ return null;
+ }
+
+ _gameTicker.StartGameRule(ruleEntity);
+ _activeRules.Add(ruleEntity);
+
+ return comp;
+ }
+
+ ///
+ /// Delete the instance of the rule entity.
+ ///
+ ///
+ /// true if was deleted successfully
+ public bool DeleteInstance(EntityUid uid)
+ {
+ if (!TryComp(uid, out var comp))
+ {
+ return false;
+ }
+
+ comp.RoundState = RoundState.NotInProgress;
+
+ // TODO: maybe delete all players from the round if deleting the map fucks that up?
+
+ if (comp.CurrentMap.HasValue)
+ _mapManager.DeleteMap(comp.CurrentMap.Value);
+
+ _gameTicker.EndGameRule(uid);
+ _activeRules.Remove(uid);
+
+ return true;
+ }
+
+
+
+ public List TeamsEligibleToJoin(ViolenceRuleComponent comp)
+ {
+ var teamList = new List();
+
+ foreach (var team in comp.Teams)
+ {
+ var teamCount = comp.TeamMembers.Values.Count(teamId => teamId == team);
+
+ if (comp.MaxPlayers.TryGetValue(team, out var maxPlayers))
+ {
+ if (teamCount < maxPlayers)
+ {
+ teamList.Add(team);
+ }
+ }
+ }
+
+ return teamList;
+ }
+
+ /*
+ private void OnRoundEndTextAppend(RoundEndTextAppendEvent ev)
+ {
+ var query = EntityQueryEnumerator();
+ while (query.MoveNext(out var uid, out var ruleComponent, out var point, out var rule))
+ {
+ if (!GameTicker.IsGameRuleAdded(uid, rule))
+ continue;
+
+
+ if (ruleComponent.MatchVictor != null && _player.TryGetPlayerData(ruleComponent.MatchVictor.Value, out var data)) // get the team data here
+ {
+ ev.AddLine(Loc.GetString("point-scoreboard-winner", ("player", data.UserName)));
+ ev.AddLine("");
+ }
+
+ ev.AddLine(Loc.GetString("point-scoreboard-header")); // edit this, probably
+ ev.AddLine(new FormattedMessage(point.Scoreboard).ToMarkup());
+ }
+ }
+ */
+}
diff --git a/Content.Shared/Points/PointManagerComponent.cs b/Content.Shared/Points/PointManagerComponent.cs
index 6c5bf6b0fa3..e39b6b88ec2 100644
--- a/Content.Shared/Points/PointManagerComponent.cs
+++ b/Content.Shared/Points/PointManagerComponent.cs
@@ -18,9 +18,22 @@ public sealed partial class PointManagerComponent : Component
[DataField, AutoNetworkedField]
public Dictionary Points = new();
+ ///
+ /// WHITE EDIT. A dictionary for team points, used for Violence gamemode.
+ ///
+ [DataField, AutoNetworkedField]
+ public Dictionary TeamPoints = new();
+
+
///
/// A text-only version of the scoreboard used by the client.
///
[DataField, AutoNetworkedField]
public FormattedMessage Scoreboard = new();
+
+ ///
+ /// A text-only version of the scoreboard used by the client.
+ ///
+ [DataField, AutoNetworkedField]
+ public FormattedMessage TeamScoreboard = new();
}
diff --git a/Content.Shared/Points/SharedPointSystem.cs b/Content.Shared/Points/SharedPointSystem.cs
index 978f4bca42e..36bedade155 100644
--- a/Content.Shared/Points/SharedPointSystem.cs
+++ b/Content.Shared/Points/SharedPointSystem.cs
@@ -75,6 +75,33 @@ public virtual FormattedMessage GetScoreboard(EntityUid uid, PointManagerCompone
{
return new FormattedMessage();
}
+
+ // WD EDIT START. Team points for Violence gamemode
+
+ ///
+ /// Ensures that a player is being tracked by the PointManager, giving them a default score of 0.
+ ///
+ public void EnsureTeam(ushort team, EntityUid uid, PointManagerComponent? component = null)
+ {
+ if (!Resolve(uid, ref component))
+ return;
+
+ if (component.TeamPoints.ContainsKey(team))
+ return;
+
+ component.TeamPoints.Add(team, FixedPoint2.Zero);
+ }
+
+ ///
+ /// Returns a formatted message containing a ranking of all the teams and their scores.
+ /// I don't even know if i should leave this here. Why do you even need PointSystem AND SharedPointSystem?
+ ///
+ public virtual FormattedMessage GetTeamScoreboard(EntityUid uid, PointManagerComponent? component = null)
+ {
+ return new FormattedMessage();
+ }
+
+ // WD EDIT END
}
///
@@ -84,3 +111,11 @@ public virtual FormattedMessage GetScoreboard(EntityUid uid, PointManagerCompone
///
[ByRefEvent]
public readonly record struct PlayerPointChangedEvent(NetUserId Player, FixedPoint2 Points);
+
+///
+/// WD EDIT. Event raised on the point manager entity and broadcasted whenever a team's points change.
+///
+///
+///
+[ByRefEvent]
+public readonly record struct TeamPointChangedEvent(ushort Team, FixedPoint2 Points);
diff --git a/Resources/Maps/_Miracle/violenceTestMap.yml b/Resources/Maps/_Miracle/violenceTestMap.yml
new file mode 100644
index 00000000000..5fa9f845032
--- /dev/null
+++ b/Resources/Maps/_Miracle/violenceTestMap.yml
@@ -0,0 +1,1433 @@
+meta:
+ format: 6
+ postmapinit: false
+tilemap:
+ 0: Space
+ 81: FloorReinforced
+ 130: Lattice
+entities:
+- proto: ""
+ entities:
+ - uid: 1
+ components:
+ - type: MetaData
+ name: map 1337
+ - type: Transform
+ - type: Map
+ - type: PhysicsMap
+ - type: GridTree
+ - type: MovedGrids
+ - type: Broadphase
+ - type: OccluderTree
+ - type: LoadedMap
+ - uid: 2
+ components:
+ - type: MetaData
+ name: grid
+ - type: Transform
+ pos: -8.028967,2.9101562
+ parent: 1
+ - type: MapGrid
+ chunks:
+ 0,0:
+ ind: 0,0
+ tiles: UQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ 0,-1:
+ ind: 0,-1
+ tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAA
+ version: 6
+ 1,0:
+ ind: 1,0
+ tiles: UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ 1,-1:
+ ind: 1,-1
+ tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ -1,-1:
+ ind: -1,-1
+ tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ - type: Broadphase
+ - type: Physics
+ bodyStatus: InAir
+ angularDamping: 0.05
+ linearDamping: 0.05
+ fixedRotation: False
+ bodyType: Dynamic
+ - type: Fixtures
+ fixtures: {}
+ - type: OccluderTree
+ - type: SpreaderGrid
+ - type: Shuttle
+ - type: GridPathfinding
+ - type: Gravity
+ gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ - type: DecalGrid
+ chunkCollection:
+ version: 2
+ nodes:
+ - node:
+ color: '#FFFFFFFF'
+ id: 1
+ decals:
+ 9: 6.9687967,-1.2083154
+ - node:
+ color: '#FFFFFFFF'
+ id: 2
+ decals:
+ 3: 9.988901,-0.9758549
+ - node:
+ angle: 1.5707963267948966 rad
+ color: '#FFFFFFFF'
+ id: ArrowsGreyscale
+ decals:
+ 5: 8.767031,-3.1789799
+ 6: 6.062023,-2.2180424
+ 8: 8.945265,-2.1242924
+ - node:
+ color: '#FFFFFFFF'
+ id: disk
+ decals:
+ 0: 11.031746,-3.1004572
+ 1: 11.031746,-3.1004572
+ - type: GridAtmosphere
+ version: 2
+ data:
+ tiles:
+ 0,0:
+ 0: 255
+ 1,0:
+ 0: 255
+ 1,-2:
+ 0: 65535
+ 1,-1:
+ 0: 65535
+ 2,0:
+ 0: 255
+ 3,0:
+ 0: 255
+ 0,-3:
+ 0: 65280
+ 0,-2:
+ 0: 65535
+ 0,-1:
+ 0: 65535
+ 1,-3:
+ 0: 65280
+ 2,-3:
+ 0: 65280
+ 2,-2:
+ 0: 65535
+ 2,-1:
+ 0: 65535
+ 3,-3:
+ 0: 65280
+ 3,-2:
+ 0: 65535
+ 3,-1:
+ 0: 65535
+ 4,0:
+ 0: 17
+ 4,-3:
+ 0: 4352
+ 4,-2:
+ 0: 4369
+ 4,-1:
+ 0: 4369
+ -1,-2:
+ 0: 61440
+ -1,-1:
+ 0: 4095
+ uniqueMixes:
+ - volume: 2500
+ temperature: 293.15
+ moles:
+ - 21.824879
+ - 82.10312
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ chunkSize: 4
+ - type: GasTileOverlay
+ - type: RadiationGridResistance
+ - uid: 182
+ components:
+ - type: MetaData
+ name: grid
+ - type: Transform
+ pos: -8.028967,1.9101562
+ parent: 1
+ - type: MapGrid
+ chunks:
+ 0,0:
+ ind: 0,0
+ tiles: ggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ - type: Broadphase
+ - type: Physics
+ bodyStatus: InAir
+ angularDamping: 0.05
+ linearDamping: 0.05
+ fixedRotation: False
+ bodyType: Dynamic
+ - type: Fixtures
+ fixtures: {}
+ - type: OccluderTree
+ - type: SpreaderGrid
+ - type: Shuttle
+ - type: GridPathfinding
+ - type: Gravity
+ gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ - type: DecalGrid
+ chunkCollection:
+ version: 2
+ nodes: []
+ - uid: 183
+ components:
+ - type: MetaData
+ name: grid
+ - type: Transform
+ pos: -8.028967,0.91015625
+ parent: 1
+ - type: MapGrid
+ chunks:
+ 0,0:
+ ind: 0,0
+ tiles: ggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ - type: Broadphase
+ - type: Physics
+ bodyStatus: InAir
+ angularDamping: 0.05
+ linearDamping: 0.05
+ fixedRotation: False
+ bodyType: Dynamic
+ - type: Fixtures
+ fixtures: {}
+ - type: OccluderTree
+ - type: SpreaderGrid
+ - type: Shuttle
+ - type: GridPathfinding
+ - type: Gravity
+ gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ - type: DecalGrid
+ chunkCollection:
+ version: 2
+ nodes: []
+ - uid: 184
+ components:
+ - type: MetaData
+ name: grid
+ - type: Transform
+ pos: -8.028967,-0.08984375
+ parent: 1
+ - type: MapGrid
+ chunks:
+ 0,0:
+ ind: 0,0
+ tiles: ggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ - type: Broadphase
+ - type: Physics
+ bodyStatus: InAir
+ angularDamping: 0.05
+ linearDamping: 0.05
+ fixedRotation: False
+ bodyType: Dynamic
+ - type: Fixtures
+ fixtures: {}
+ - type: OccluderTree
+ - type: SpreaderGrid
+ - type: Shuttle
+ - type: GridPathfinding
+ - type: Gravity
+ gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ - type: DecalGrid
+ chunkCollection:
+ version: 2
+ nodes: []
+ - uid: 185
+ components:
+ - type: MetaData
+ name: grid
+ - type: Transform
+ pos: -8.028967,-1.0898438
+ parent: 1
+ - type: MapGrid
+ chunks:
+ 0,0:
+ ind: 0,0
+ tiles: ggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ - type: Broadphase
+ - type: Physics
+ bodyStatus: InAir
+ angularDamping: 0.05
+ linearDamping: 0.05
+ fixedRotation: False
+ bodyType: Dynamic
+ - type: Fixtures
+ fixtures: {}
+ - type: OccluderTree
+ - type: SpreaderGrid
+ - type: Shuttle
+ - type: GridPathfinding
+ - type: Gravity
+ gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ - type: DecalGrid
+ chunkCollection:
+ version: 2
+ nodes: []
+ - uid: 186
+ components:
+ - type: MetaData
+ name: grid
+ - type: Transform
+ pos: -8.028967,-2.0898438
+ parent: 1
+ - type: MapGrid
+ chunks:
+ 0,0:
+ ind: 0,0
+ tiles: ggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ - type: Broadphase
+ - type: Physics
+ bodyStatus: InAir
+ angularDamping: 0.05
+ linearDamping: 0.05
+ fixedRotation: False
+ bodyType: Dynamic
+ - type: Fixtures
+ fixtures: {}
+ - type: OccluderTree
+ - type: SpreaderGrid
+ - type: Shuttle
+ - type: GridPathfinding
+ - type: Gravity
+ gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ - type: DecalGrid
+ chunkCollection:
+ version: 2
+ nodes: []
+ - uid: 187
+ components:
+ - type: MetaData
+ name: grid
+ - type: Transform
+ pos: -8.028967,-3.0898438
+ parent: 1
+ - type: MapGrid
+ chunks:
+ 0,0:
+ ind: 0,0
+ tiles: ggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ - type: Broadphase
+ - type: Physics
+ bodyStatus: InAir
+ angularDamping: 0.05
+ linearDamping: 0.05
+ fixedRotation: False
+ bodyType: Dynamic
+ - type: Fixtures
+ fixtures: {}
+ - type: OccluderTree
+ - type: SpreaderGrid
+ - type: Shuttle
+ - type: GridPathfinding
+ - type: Gravity
+ gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ - type: DecalGrid
+ chunkCollection:
+ version: 2
+ nodes: []
+ - uid: 188
+ components:
+ - type: MetaData
+ name: grid
+ - type: Transform
+ pos: -8.028967,-4.0898438
+ parent: 1
+ - type: MapGrid
+ chunks:
+ 0,0:
+ ind: 0,0
+ tiles: ggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ - type: Broadphase
+ - type: Physics
+ bodyStatus: InAir
+ angularDamping: 0.05
+ linearDamping: 0.05
+ fixedRotation: False
+ bodyType: Dynamic
+ - type: Fixtures
+ fixtures: {}
+ - type: OccluderTree
+ - type: SpreaderGrid
+ - type: Shuttle
+ - type: GridPathfinding
+ - type: Gravity
+ gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ - type: DecalGrid
+ chunkCollection:
+ version: 2
+ nodes: []
+ - uid: 189
+ components:
+ - type: MetaData
+ name: grid
+ - type: Transform
+ pos: -8.028967,-5.0898438
+ parent: 1
+ - type: MapGrid
+ chunks:
+ 0,0:
+ ind: 0,0
+ tiles: ggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ version: 6
+ - type: Broadphase
+ - type: Physics
+ bodyStatus: InAir
+ angularDamping: 0.05
+ linearDamping: 0.05
+ fixedRotation: False
+ bodyType: Dynamic
+ - type: Fixtures
+ fixtures: {}
+ - type: OccluderTree
+ - type: SpreaderGrid
+ - type: Shuttle
+ - type: GridPathfinding
+ - type: Gravity
+ gravityShakeSound: !type:SoundPathSpecifier
+ path: /Audio/Effects/alert.ogg
+ - type: DecalGrid
+ chunkCollection:
+ version: 2
+ nodes: []
+- proto: AdminHypo
+ entities:
+ - uid: 175
+ components:
+ - type: Transform
+ pos: 5.215679,0.5063157
+ parent: 2
+- proto: AirlockGlass
+ entities:
+ - uid: 178
+ components:
+ - type: Transform
+ pos: 1.5,-0.5
+ parent: 2
+- proto: AlwaysPoweredWallLight
+ entities:
+ - uid: 3
+ components:
+ - type: Transform
+ anchored: False
+ pos: 3.5,0.5
+ parent: 2
+ - uid: 4
+ components:
+ - type: Transform
+ pos: 15.5,0.5
+ parent: 2
+ - uid: 5
+ components:
+ - type: Transform
+ rot: -1.5707963267948966 rad
+ pos: 15.5,-4.5
+ parent: 2
+ - uid: 6
+ components:
+ - type: Transform
+ rot: 3.141592653589793 rad
+ pos: 14.5,-8.5
+ parent: 2
+ - uid: 7
+ components:
+ - type: Transform
+ rot: 3.141592653589793 rad
+ pos: 9.5,-8.5
+ parent: 2
+ - uid: 8
+ components:
+ - type: Transform
+ rot: 3.141592653589793 rad
+ pos: 3.5,-8.5
+ parent: 2
+ - uid: 9
+ components:
+ - type: Transform
+ anchored: False
+ rot: 1.5707963267948966 rad
+ pos: 1.5,-1.5
+ parent: 2
+ - uid: 10
+ components:
+ - type: Transform
+ anchored: False
+ pos: 9.5,0.5
+ parent: 2
+- proto: APCHyperCapacity
+ entities:
+ - uid: 11
+ components:
+ - type: Transform
+ pos: -0.5,-2.5
+ parent: 2
+- proto: BaseUplinkRadioDebug
+ entities:
+ - uid: 12
+ components:
+ - type: Transform
+ pos: 12.542767,-5.162384
+ parent: 2
+- proto: CableApcExtension
+ entities:
+ - uid: 13
+ components:
+ - type: Transform
+ pos: -0.5,-2.5
+ parent: 2
+ - uid: 14
+ components:
+ - type: Transform
+ pos: -0.5,-2.5
+ parent: 2
+ - uid: 15
+ components:
+ - type: Transform
+ pos: -1.5,-2.5
+ parent: 2
+ - uid: 16
+ components:
+ - type: Transform
+ pos: 0.5,-2.5
+ parent: 2
+ - uid: 17
+ components:
+ - type: Transform
+ pos: 4.5,-7.5
+ parent: 2
+ - uid: 18
+ components:
+ - type: Transform
+ pos: 7.5,-7.5
+ parent: 2
+ - uid: 19
+ components:
+ - type: Transform
+ pos: 9.5,-7.5
+ parent: 2
+ - uid: 20
+ components:
+ - type: Transform
+ pos: 10.5,-3.5
+ parent: 2
+ - uid: 21
+ components:
+ - type: Transform
+ pos: 10.5,-2.5
+ parent: 2
+ - uid: 22
+ components:
+ - type: Transform
+ pos: 11.5,-2.5
+ parent: 2
+ - uid: 23
+ components:
+ - type: Transform
+ pos: 12.5,-2.5
+ parent: 2
+ - uid: 24
+ components:
+ - type: Transform
+ pos: 13.5,-2.5
+ parent: 2
+ - uid: 25
+ components:
+ - type: Transform
+ pos: 14.5,-2.5
+ parent: 2
+ - uid: 26
+ components:
+ - type: Transform
+ pos: 2.5,-7.5
+ parent: 2
+ - uid: 27
+ components:
+ - type: Transform
+ pos: 14.5,-7.5
+ parent: 2
+ - uid: 28
+ components:
+ - type: Transform
+ pos: 11.5,-7.5
+ parent: 2
+ - uid: 29
+ components:
+ - type: Transform
+ pos: 13.5,-7.5
+ parent: 2
+ - uid: 30
+ components:
+ - type: Transform
+ pos: 12.5,-7.5
+ parent: 2
+ - uid: 31
+ components:
+ - type: Transform
+ pos: 3.5,-7.5
+ parent: 2
+ - uid: 32
+ components:
+ - type: Transform
+ pos: 6.5,-7.5
+ parent: 2
+ - uid: 33
+ components:
+ - type: Transform
+ pos: 8.5,-7.5
+ parent: 2
+ - uid: 34
+ components:
+ - type: Transform
+ pos: 10.5,-7.5
+ parent: 2
+ - uid: 35
+ components:
+ - type: Transform
+ pos: 5.5,-7.5
+ parent: 2
+ - uid: 36
+ components:
+ - type: Transform
+ pos: 1.5,-2.5
+ parent: 2
+ - uid: 37
+ components:
+ - type: Transform
+ pos: 0.5,-2.5
+ parent: 2
+ - uid: 38
+ components:
+ - type: Transform
+ pos: 2.5,-2.5
+ parent: 2
+ - uid: 39
+ components:
+ - type: Transform
+ pos: 8.5,-2.5
+ parent: 2
+ - uid: 40
+ components:
+ - type: Transform
+ pos: 4.5,-2.5
+ parent: 2
+ - uid: 41
+ components:
+ - type: Transform
+ pos: 6.5,-2.5
+ parent: 2
+ - uid: 42
+ components:
+ - type: Transform
+ pos: 3.5,-2.5
+ parent: 2
+ - uid: 43
+ components:
+ - type: Transform
+ pos: 5.5,-2.5
+ parent: 2
+ - uid: 44
+ components:
+ - type: Transform
+ pos: 9.5,-2.5
+ parent: 2
+ - uid: 45
+ components:
+ - type: Transform
+ pos: 10.5,-5.5
+ parent: 2
+ - uid: 46
+ components:
+ - type: Transform
+ pos: 7.5,-2.5
+ parent: 2
+ - uid: 47
+ components:
+ - type: Transform
+ pos: 10.5,-6.5
+ parent: 2
+ - uid: 48
+ components:
+ - type: Transform
+ pos: 10.5,-4.5
+ parent: 2
+- proto: CableHV
+ entities:
+ - uid: 49
+ components:
+ - type: Transform
+ pos: -2.5,-2.5
+ parent: 2
+ - uid: 50
+ components:
+ - type: Transform
+ pos: -1.5,-2.5
+ parent: 2
+- proto: CableMV
+ entities:
+ - uid: 51
+ components:
+ - type: Transform
+ pos: 5.5,-2.5
+ parent: 2
+ - uid: 52
+ components:
+ - type: Transform
+ pos: 6.5,-2.5
+ parent: 2
+ - uid: 53
+ components:
+ - type: Transform
+ pos: 8.5,-2.5
+ parent: 2
+ - uid: 54
+ components:
+ - type: Transform
+ pos: 7.5,-2.5
+ parent: 2
+ - uid: 55
+ components:
+ - type: Transform
+ pos: 3.5,-2.5
+ parent: 2
+ - uid: 56
+ components:
+ - type: Transform
+ pos: 1.5,-2.5
+ parent: 2
+ - uid: 57
+ components:
+ - type: Transform
+ pos: 4.5,-2.5
+ parent: 2
+ - uid: 58
+ components:
+ - type: Transform
+ pos: -1.5,-2.5
+ parent: 2
+ - uid: 59
+ components:
+ - type: Transform
+ pos: -0.5,-2.5
+ parent: 2
+ - uid: 60
+ components:
+ - type: Transform
+ pos: 0.5,-2.5
+ parent: 2
+ - uid: 61
+ components:
+ - type: Transform
+ pos: 15.5,-2.5
+ parent: 2
+ - uid: 62
+ components:
+ - type: Transform
+ pos: 2.5,-2.5
+ parent: 2
+ - uid: 63
+ components:
+ - type: Transform
+ pos: 0.5,-2.5
+ parent: 2
+ - uid: 64
+ components:
+ - type: Transform
+ pos: 10.5,-2.5
+ parent: 2
+ - uid: 65
+ components:
+ - type: Transform
+ pos: 11.5,-2.5
+ parent: 2
+ - uid: 66
+ components:
+ - type: Transform
+ pos: 12.5,-2.5
+ parent: 2
+ - uid: 67
+ components:
+ - type: Transform
+ pos: 13.5,-2.5
+ parent: 2
+ - uid: 68
+ components:
+ - type: Transform
+ pos: 14.5,-2.5
+ parent: 2
+ - uid: 69
+ components:
+ - type: Transform
+ pos: 9.5,-2.5
+ parent: 2
+- proto: DebugGenerator
+ entities:
+ - uid: 70
+ components:
+ - type: Transform
+ pos: -2.5,-2.5
+ parent: 2
+ - uid: 71
+ components:
+ - type: Transform
+ pos: -2.5,-2.5
+ parent: 2
+- proto: EmagUnlimited
+ entities:
+ - uid: 168
+ components:
+ - type: Transform
+ pos: 2.6720915,-2.5398998
+ parent: 2
+- proto: FloorChasmEntity
+ entities:
+ - uid: 169
+ components:
+ - type: Transform
+ pos: 1.5,-4.5
+ parent: 2
+ - uid: 170
+ components:
+ - type: Transform
+ pos: 1.5,-5.5
+ parent: 2
+ - uid: 171
+ components:
+ - type: Transform
+ pos: 1.5,-6.5
+ parent: 2
+ - uid: 172
+ components:
+ - type: Transform
+ pos: 1.5,-7.5
+ parent: 2
+- proto: GravityGeneratorMini
+ entities:
+ - uid: 173
+ components:
+ - type: Transform
+ pos: -0.5,-3.5
+ parent: 2
+- proto: HardlightSpearImplanter
+ entities:
+ - uid: 72
+ components:
+ - type: Transform
+ pos: 11.990374,-5.15222
+ parent: 2
+- proto: MeleeDebugGib
+ entities:
+ - uid: 73
+ components:
+ - type: Transform
+ pos: 10.240486,-5.3331795
+ parent: 2
+- proto: RCDExperimental
+ entities:
+ - uid: 174
+ components:
+ - type: Transform
+ pos: 4.5301466,0.42327738
+ parent: 2
+- proto: Recycler
+ entities:
+ - uid: 167
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: 1.5,-2.5
+ parent: 2
+- proto: SpawnPointLatejoinViolenceOne
+ entities:
+ - uid: 181
+ components:
+ - type: Transform
+ pos: 7.5,-2.5
+ parent: 2
+- proto: SpawnPointLatejoinViolenceTwo
+ entities:
+ - uid: 74
+ components:
+ - type: Transform
+ pos: 10.5,-2.5
+ parent: 2
+- proto: SpawnPointViolenceOne
+ entities:
+ - uid: 180
+ components:
+ - type: Transform
+ pos: 7.5,-1.5
+ parent: 2
+- proto: SpawnPointViolenceTwo
+ entities:
+ - uid: 75
+ components:
+ - type: Transform
+ pos: 10.5,-1.5
+ parent: 2
+- proto: SubstationBasic
+ entities:
+ - uid: 76
+ components:
+ - type: Transform
+ pos: -1.5,-2.5
+ parent: 2
+ - uid: 77
+ components:
+ - type: Transform
+ pos: -1.5,-2.5
+ parent: 2
+- proto: TablePlasmaGlass
+ entities:
+ - uid: 78
+ components:
+ - type: Transform
+ pos: 9.5,-5.5
+ parent: 2
+ - uid: 79
+ components:
+ - type: Transform
+ pos: 7.5,-5.5
+ parent: 2
+ - uid: 80
+ components:
+ - type: Transform
+ pos: 8.5,-5.5
+ parent: 2
+ - uid: 81
+ components:
+ - type: Transform
+ pos: 6.5,-5.5
+ parent: 2
+ - uid: 82
+ components:
+ - type: Transform
+ pos: 12.5,-5.5
+ parent: 2
+ - uid: 83
+ components:
+ - type: Transform
+ pos: 11.5,-5.5
+ parent: 2
+ - uid: 84
+ components:
+ - type: Transform
+ pos: 10.5,-5.5
+ parent: 2
+- proto: TargetClown
+ entities:
+ - uid: 85
+ components:
+ - type: Transform
+ pos: 15.5,-2.5
+ parent: 2
+- proto: TargetStrange
+ entities:
+ - uid: 86
+ components:
+ - type: Transform
+ pos: 15.5,-3.5
+ parent: 2
+- proto: TargetSyndicate
+ entities:
+ - uid: 87
+ components:
+ - type: Transform
+ pos: 15.5,-1.5
+ parent: 2
+- proto: WallPlastitaniumIndestructible
+ entities:
+ - uid: 88
+ components:
+ - type: Transform
+ pos: 11.5,-9.5
+ parent: 2
+ - uid: 89
+ components:
+ - type: Transform
+ pos: 0.5,-8.5
+ parent: 2
+ - uid: 90
+ components:
+ - type: Transform
+ pos: 0.5,-9.5
+ parent: 2
+ - uid: 91
+ components:
+ - type: Transform
+ pos: 0.5,1.5
+ parent: 2
+ - uid: 92
+ components:
+ - type: Transform
+ pos: 0.5,0.5
+ parent: 2
+ - uid: 93
+ components:
+ - type: Transform
+ pos: 0.5,-0.5
+ parent: 2
+ - uid: 94
+ components:
+ - type: Transform
+ pos: 0.5,-1.5
+ parent: 2
+ - uid: 95
+ components:
+ - type: Transform
+ pos: 0.5,-2.5
+ parent: 2
+ - uid: 96
+ components:
+ - type: Transform
+ pos: 0.5,-3.5
+ parent: 2
+ - uid: 97
+ components:
+ - type: Transform
+ pos: 0.5,-4.5
+ parent: 2
+ - uid: 98
+ components:
+ - type: Transform
+ pos: 0.5,-5.5
+ parent: 2
+ - uid: 99
+ components:
+ - type: Transform
+ pos: 0.5,-6.5
+ parent: 2
+ - uid: 100
+ components:
+ - type: Transform
+ pos: 0.5,-7.5
+ parent: 2
+ - uid: 101
+ components:
+ - type: Transform
+ pos: 12.5,-9.5
+ parent: 2
+ - uid: 102
+ components:
+ - type: Transform
+ pos: 13.5,-9.5
+ parent: 2
+ - uid: 103
+ components:
+ - type: Transform
+ pos: 14.5,-9.5
+ parent: 2
+ - uid: 104
+ components:
+ - type: Transform
+ pos: 15.5,-9.5
+ parent: 2
+ - uid: 105
+ components:
+ - type: Transform
+ pos: 16.5,-9.5
+ parent: 2
+ - uid: 106
+ components:
+ - type: Transform
+ pos: 1.5,-9.5
+ parent: 2
+ - uid: 107
+ components:
+ - type: Transform
+ pos: 2.5,-9.5
+ parent: 2
+ - uid: 108
+ components:
+ - type: Transform
+ pos: 3.5,-9.5
+ parent: 2
+ - uid: 109
+ components:
+ - type: Transform
+ pos: 4.5,-9.5
+ parent: 2
+ - uid: 110
+ components:
+ - type: Transform
+ pos: 5.5,-9.5
+ parent: 2
+ - uid: 111
+ components:
+ - type: Transform
+ pos: 6.5,-9.5
+ parent: 2
+ - uid: 112
+ components:
+ - type: Transform
+ pos: 7.5,-9.5
+ parent: 2
+ - uid: 113
+ components:
+ - type: Transform
+ pos: 8.5,-9.5
+ parent: 2
+ - uid: 114
+ components:
+ - type: Transform
+ pos: 9.5,-9.5
+ parent: 2
+ - uid: 115
+ components:
+ - type: Transform
+ pos: 10.5,-9.5
+ parent: 2
+ - uid: 116
+ components:
+ - type: Transform
+ pos: 16.5,1.5
+ parent: 2
+ - uid: 117
+ components:
+ - type: Transform
+ pos: 16.5,-8.5
+ parent: 2
+ - uid: 118
+ components:
+ - type: Transform
+ pos: 16.5,-7.5
+ parent: 2
+ - uid: 119
+ components:
+ - type: Transform
+ pos: 16.5,-6.5
+ parent: 2
+ - uid: 120
+ components:
+ - type: Transform
+ pos: 16.5,-5.5
+ parent: 2
+ - uid: 121
+ components:
+ - type: Transform
+ pos: 16.5,-4.5
+ parent: 2
+ - uid: 122
+ components:
+ - type: Transform
+ pos: 16.5,-3.5
+ parent: 2
+ - uid: 123
+ components:
+ - type: Transform
+ pos: 16.5,-2.5
+ parent: 2
+ - uid: 124
+ components:
+ - type: Transform
+ pos: 16.5,-1.5
+ parent: 2
+ - uid: 125
+ components:
+ - type: Transform
+ pos: 16.5,-0.5
+ parent: 2
+ - uid: 126
+ components:
+ - type: Transform
+ pos: 16.5,0.5
+ parent: 2
+ - uid: 127
+ components:
+ - type: Transform
+ pos: 6.5,1.5
+ parent: 2
+ - uid: 128
+ components:
+ - type: Transform
+ pos: 5.5,1.5
+ parent: 2
+ - uid: 129
+ components:
+ - type: Transform
+ pos: 4.5,1.5
+ parent: 2
+ - uid: 130
+ components:
+ - type: Transform
+ pos: 3.5,1.5
+ parent: 2
+ - uid: 131
+ components:
+ - type: Transform
+ pos: 2.5,1.5
+ parent: 2
+ - uid: 132
+ components:
+ - type: Transform
+ pos: 1.5,1.5
+ parent: 2
+ - uid: 133
+ components:
+ - type: Transform
+ pos: 15.5,1.5
+ parent: 2
+ - uid: 134
+ components:
+ - type: Transform
+ pos: 14.5,1.5
+ parent: 2
+ - uid: 135
+ components:
+ - type: Transform
+ pos: 13.5,1.5
+ parent: 2
+ - uid: 136
+ components:
+ - type: Transform
+ pos: 12.5,1.5
+ parent: 2
+ - uid: 137
+ components:
+ - type: Transform
+ pos: 11.5,1.5
+ parent: 2
+ - uid: 138
+ components:
+ - type: Transform
+ pos: 10.5,1.5
+ parent: 2
+ - uid: 139
+ components:
+ - type: Transform
+ pos: 9.5,1.5
+ parent: 2
+ - uid: 140
+ components:
+ - type: Transform
+ pos: 8.5,1.5
+ parent: 2
+ - uid: 141
+ components:
+ - type: Transform
+ pos: 7.5,1.5
+ parent: 2
+ - uid: 142
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -0.5,-1.5
+ parent: 2
+ - uid: 143
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -1.5,-1.5
+ parent: 2
+ - uid: 144
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -2.5,-1.5
+ parent: 2
+ - uid: 145
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -3.5,-1.5
+ parent: 2
+ - uid: 146
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -3.5,-2.5
+ parent: 2
+ - uid: 147
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -3.5,-3.5
+ parent: 2
+ - uid: 148
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -3.5,-4.5
+ parent: 2
+ - uid: 149
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -2.5,-4.5
+ parent: 2
+ - uid: 150
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -1.5,-4.5
+ parent: 2
+ - uid: 151
+ components:
+ - type: Transform
+ rot: 1.5707963267948966 rad
+ pos: -0.5,-4.5
+ parent: 2
+- proto: WallShuttle
+ entities:
+ - uid: 176
+ components:
+ - type: Transform
+ pos: 2.5,-0.5
+ parent: 2
+ - uid: 177
+ components:
+ - type: Transform
+ pos: 2.5,0.5
+ parent: 2
+- proto: WeaponAntiqueLaser
+ entities:
+ - uid: 161
+ components:
+ - type: Transform
+ pos: 7.7074156,-5.3778133
+ parent: 2
+ - uid: 162
+ components:
+ - type: Transform
+ pos: 7.7074156,-5.3778133
+ parent: 2
+- proto: WeaponLightMachineGunL6
+ entities:
+ - uid: 152
+ components:
+ - type: Transform
+ pos: 10.812881,-5.185898
+ parent: 2
+- proto: WeaponMinigun
+ entities:
+ - uid: 153
+ components:
+ - type: Transform
+ pos: 11.87611,-5.377356
+ parent: 2
+- proto: WeaponPistolDebug
+ entities:
+ - uid: 157
+ components:
+ - type: Transform
+ pos: 9.910168,-5.310079
+ parent: 2
+- proto: WeaponPistolN1984
+ entities:
+ - uid: 154
+ components:
+ - type: Transform
+ pos: 10.672256,-5.5374603
+ parent: 2
+- proto: WeaponPoweredCrossbow
+ entities:
+ - uid: 160
+ components:
+ - type: Transform
+ pos: 8.176166,-5.541876
+ parent: 2
+- proto: WeaponPulseRifle
+ entities:
+ - uid: 155
+ components:
+ - type: Transform
+ pos: 12.50983,-5.482825
+ parent: 2
+- proto: WeaponShotgunBulldog
+ entities:
+ - uid: 159
+ components:
+ - type: Transform
+ pos: 8.575228,-5.320423
+ parent: 2
+- proto: WeaponStaffHealing
+ entities:
+ - uid: 166
+ components:
+ - type: Transform
+ pos: 6.2598753,-5.3296022
+ parent: 2
+- proto: WeaponSubMachineGunC20r
+ entities:
+ - uid: 156
+ components:
+ - type: Transform
+ pos: 11.4912,-5.3998337
+ parent: 2
+- proto: WeaponTeslaGun
+ entities:
+ - uid: 158
+ components:
+ - type: Transform
+ pos: 9.212797,-5.488595
+ parent: 2
+- proto: WeaponTurretHostile
+ entities:
+ - uid: 179
+ components:
+ - type: Transform
+ pos: 1.5,0.5
+ parent: 2
+- proto: WeaponWandDeath
+ entities:
+ - uid: 163
+ components:
+ - type: Transform
+ pos: 7.1136885,-5.448126
+ parent: 2
+- proto: WeaponWandFireball
+ entities:
+ - uid: 164
+ components:
+ - type: Transform
+ pos: 6.9261885,-5.307501
+ parent: 2
+- proto: WeaponWandPolymorphCarp
+ entities:
+ - uid: 165
+ components:
+ - type: Transform
+ pos: 6.5980635,-5.354376
+ parent: 2
+...
diff --git a/Resources/Prototypes/_Miracle/Violence/game_presets.yml b/Resources/Prototypes/_Miracle/Violence/game_presets.yml
new file mode 100644
index 00000000000..e02abfc9b0e
--- /dev/null
+++ b/Resources/Prototypes/_Miracle/Violence/game_presets.yml
@@ -0,0 +1 @@
+
diff --git a/Resources/Prototypes/_Miracle/Violence/prototypes.yml b/Resources/Prototypes/_Miracle/Violence/prototypes.yml
new file mode 100644
index 00000000000..4cf03b2380c
--- /dev/null
+++ b/Resources/Prototypes/_Miracle/Violence/prototypes.yml
@@ -0,0 +1,93 @@
+- type: gamePreset
+ id: ViolenceDebug
+ alias:
+ - violenceTest
+ - violenceDebug
+ name: Violence
+ description: Violence
+ showInVote: false
+ rules:
+ - ViolenceTestRule
+
+- type: entity
+ id: ViolenceTestRule
+ parent: BaseGameRule
+ noSpawn: true
+ components:
+ - type: ViolenceRule
+ teams:
+ shop:
+ pointCap: 5
+ roundDuration: 5 # timespan issues?
+ killReward: 300
+ assistReward: 100
+ aliveReward: 300
+ skillIssuePenalty: 300 # penalty for suicide or being thrown in lava
+ mapPool: ViolenceTestMapPool
+
+- type: gameMapPool
+ id: ViolenceTestMapPool
+ maps:
+ - ViolenceTestMap
+
+- type: entity
+ id: SpawnPointViolenceOne
+ parent: SpawnPointJobBase
+ name: violence team 1 spawner
+ components:
+ - type: SpawnPoint
+ job_id: ViolenceJob
+ teamId: 1
+ - type: Sprite # TODO: edit this
+ layers:
+ - state: green
+ - state: qm
+
+- type: entity
+ name: violence latejoin spawn point (team 1)
+ id: SpawnPointLatejoinViolenceOne
+ parent: SpawnPointJobBase
+ components:
+ - type: Sprite
+ state: green
+ - type: SpawnPoint
+ spawn_type: LateJoin
+ teamId: 1
+
+- type: entity
+ id: SpawnPointViolenceTwo
+ parent: SpawnPointJobBase
+ name: violence team 2 spawner
+ components:
+ - type: SpawnPoint
+ job_id: ViolenceJob
+ teamId: 2
+ - type: Sprite # TODO: edit this
+ layers:
+ - state: green
+ - state: qm
+
+- type: entity
+ name: violence latejoin spawn point (team 2)
+ id: SpawnPointLatejoinViolenceTwo
+ parent: SpawnPointJobBase
+ components:
+ - type: Sprite
+ state: green
+ - type: SpawnPoint
+ spawn_type: LateJoin
+ teamId: 2
+
+- type: job
+ id: ViolenceJob
+ name: job-name-violence
+ description: job-description-violence
+ playTimeTracker: JobViolence
+ startingGear: CentcomGear
+ icon: "JobIconPassenger"
+ canBeAntag: false
+ access:
+ - Maintenance
+
+- type: playTimeTracker
+ id: JobViolence
diff --git a/Resources/Prototypes/_Miracle/Violence/testmap.yml b/Resources/Prototypes/_Miracle/Violence/testmap.yml
new file mode 100644
index 00000000000..355d85221f7
--- /dev/null
+++ b/Resources/Prototypes/_Miracle/Violence/testmap.yml
@@ -0,0 +1,27 @@
+- type: gameMap
+ id: ViolenceTestMap
+ mapName: Meteor Arena
+ mapPath: /Maps/_Miracle/violenceTestMap.yml
+ minPlayers: 0
+ stations:
+ Arena:
+ stationProto: ViolenceStation
+ components:
+ - type: StationNameSetup
+ mapNameTemplate: "Violence"
+ - type: StationJobs # maybe exclude this
+ overflowJobs:
+ - ViolenceJob
+ availableJobs:
+ ViolenceJob: [ -1, -1 ]
+
+- type: entity
+ id: ViolenceStation
+ parent:
+ - BaseStation
+ - BaseStationJobsSpawning
+ - BaseStationRecords
+ - BaseStationNanotrasen
+ noSpawn: true
+ components:
+ - type: Transform