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