Ver Fonte

TDM update 1 (#187)

* k/d tracker

* suit, helmet weights, spear range, respawn timers

* fixing waterskins, some strings

* fixes point capturing for criticals

* faster rotting

* barricade directionals, craftable recipes

* yaml fix

* map tweaks
Taislin há 7 meses atrás
pai
commit
21d0ce4a75
32 ficheiros alterados com 715 adições e 218 exclusões
  1. 11 3
      Content.Client/GameTicking/Managers/ClientGameTicker.cs
  2. 28 7
      Content.Client/LateJoin/LateJoinGui.cs
  3. 6 6
      Content.Client/RoundEnd/RoundEndSummaryWindow.cs
  4. 2 2
      Content.Client/StatusIcon/StatusIconSystem.cs
  5. 36 36
      Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs
  6. 21 4
      Content.Server/Atmos/Rotting/RottingSystem.cs
  7. 3 1
      Content.Server/GameTicking/GameTicker.GameRule.cs
  8. 33 3
      Content.Server/GameTicking/GameTicker.Lobby.cs
  9. 51 2
      Content.Server/GameTicking/GameTicker.Spawning.cs
  10. 14 8
      Content.Server/GameTicking/Rules/CaptureAreaSystem.cs
  11. 40 0
      Content.Server/GameTicking/Rules/Components/TeamDeathMatchRuleComponent.cs
  12. 7 6
      Content.Server/GameTicking/Rules/RespawnRuleSystem.cs
  13. 149 0
      Content.Server/GameTicking/Rules/TeamDeathMatchRuleSystem.cs
  14. 1 2
      Content.Shared/Atmos/Rotting/SharedRottingSystem.cs
  15. 13 0
      Content.Shared/GameTicking/SharedGameTicker.cs
  16. 41 1
      Content.Shared/Projectiles/SharedProjectileSystem.cs
  17. 3 0
      Resources/Locale/en-US/game-ticking/game-rules/rules.ftl
  18. 2 2
      Resources/Locale/en-US/game-ticking/game-ticker.ftl
  19. 2 2
      Resources/Locale/en-US/job/department.ftl
  20. 3 3
      Resources/Locale/en-US/late-join/late-join-gui.ftl
  21. 2 2
      Resources/Maps/civ/tdm/camp.yml
  22. 28 16
      Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_hats.yml
  23. 11 68
      Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_suit.yml
  24. 35 1
      Resources/Prototypes/Civ14/Entities/Objects/Storage/leather.yml
  25. 9 9
      Resources/Prototypes/Civ14/Entities/Objects/Weapons/spears.yml
  26. 11 1
      Resources/Prototypes/Civ14/Entities/Structures/Walls/barricades.yml
  27. 65 0
      Resources/Prototypes/Civ14/Recipes/Construction/barricades.yml
  28. 1 1
      Resources/Prototypes/Civ14/Recipes/Walls/walls.yml
  29. 73 4
      Resources/Prototypes/Civ14/StatusIcon/faction.yml
  30. 12 0
      Resources/Prototypes/GameRules/roundstart.yml
  31. 0 28
      Resources/Prototypes/StatusIcon/faction.yml
  32. 2 0
      Resources/Prototypes/game_presets.yml

+ 11 - 3
Content.Client/GameTicking/Managers/ClientGameTicker.cs

@@ -11,6 +11,8 @@
 using Robust.Client.UserInterface;
 using Robust.Shared.Prototypes;
 using Robust.Shared.Audio;
+using Content.Shared.NPC.Prototypes;
+using Content.Shared.NPC.Components;
 
 namespace Content.Client.GameTicking.Managers
 {
@@ -22,7 +24,7 @@ public sealed class ClientGameTicker : SharedGameTicker
         [Dependency] private readonly IClyde _clyde = default!;
         [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
 
-        private Dictionary<NetEntity, Dictionary<ProtoId<JobPrototype>, int?>>  _jobsAvailable = new();
+        private Dictionary<NetEntity, Dictionary<ProtoId<JobPrototype>, int?>> _jobsAvailable = new();
         private Dictionary<NetEntity, string> _stationNames = new();
 
         [ViewVariables] public bool AreWeReady { get; private set; }
@@ -31,6 +33,7 @@ public sealed class ClientGameTicker : SharedGameTicker
         [ViewVariables] public string? LobbyBackground { get; private set; }
         [ViewVariables] public bool DisallowedLateJoin { get; private set; }
         [ViewVariables] public string? ServerInfoBlob { get; private set; }
+        [ViewVariables] public Dictionary<ProtoId<NpcFactionPrototype>, int> PlayerFactionCounts { get; private set; } = new();
         [ViewVariables] public TimeSpan StartTime { get; private set; }
         [ViewVariables] public new bool Paused { get; private set; }
 
@@ -41,7 +44,7 @@ public sealed class ClientGameTicker : SharedGameTicker
         public event Action? LobbyStatusUpdated;
         public event Action? LobbyLateJoinStatusUpdated;
         public event Action<IReadOnlyDictionary<NetEntity, Dictionary<ProtoId<JobPrototype>, int?>>>? LobbyJobsAvailableUpdated;
-
+        public event Action? PlayerFactionCountsUpdated;
         public override void Initialize()
         {
             base.Initialize();
@@ -51,6 +54,7 @@ public override void Initialize()
             SubscribeNetworkEvent<TickerConnectionStatusEvent>(ConnectionStatus);
             SubscribeNetworkEvent<TickerLobbyStatusEvent>(LobbyStatus);
             SubscribeNetworkEvent<TickerLobbyInfoEvent>(LobbyInfo);
+            SubscribeNetworkEvent<GetPlayerFactionCounts>(OnPlayerFactionCountsReceived);
             SubscribeNetworkEvent<TickerLobbyCountdownEvent>(LobbyCountdown);
             SubscribeNetworkEvent<RoundEndMessageEvent>(RoundEnd);
             SubscribeNetworkEvent<RequestWindowAttentionEvent>(OnAttentionRequest);
@@ -134,7 +138,11 @@ private void LobbyInfo(TickerLobbyInfoEvent message)
 
             InfoBlobUpdated?.Invoke();
         }
-
+        private void OnPlayerFactionCountsReceived(GetPlayerFactionCounts ev)
+        {
+            PlayerFactionCounts = ev.FactionCounts;
+            PlayerFactionCountsUpdated?.Invoke();
+        }
         private void JoinGame(TickerJoinGameEvent message)
         {
             _stateManager.RequestStateChange<GameplayState>();

+ 28 - 7
Content.Client/LateJoin/LateJoinGui.cs

@@ -10,6 +10,7 @@
 using Content.Shared.Roles;
 using Content.Shared.StatusIcon;
 using Robust.Client.Console;
+using Robust.Shared.Log;
 using Robust.Client.GameObjects;
 using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
@@ -29,9 +30,8 @@ public sealed class LateJoinGui : DefaultWindow
         [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
         [Dependency] private readonly JobRequirementsManager _jobRequirements = default!;
         [Dependency] private readonly IClientPreferencesManager _preferencesManager = default!;
-
         public event Action<(NetEntity, string)> SelectedId;
-
+        private readonly ISawmill _sawmill;
         private readonly ClientGameTicker _gameTicker;
         private readonly SpriteSystem _sprites;
         private readonly CrewManifestSystem _crewManifest;
@@ -47,6 +47,7 @@ public LateJoinGui()
             MinSize = SetSize = new Vector2(360, 560);
             IoCManager.InjectDependencies(this);
             _sprites = _entitySystem.GetEntitySystem<SpriteSystem>();
+            _sawmill = Logger.GetSawmill("latejoin");
             _crewManifest = _entitySystem.GetEntitySystem<CrewManifestSystem>();
             _gameTicker = _entitySystem.GetEntitySystem<ClientGameTicker>();
 
@@ -66,12 +67,13 @@ public LateJoinGui()
             SelectedId += x =>
             {
                 var (station, jobId) = x;
-                Logger.InfoS("latejoin", $"Late joining as ID: {jobId}");
+                _sawmill.Info("latejoin", $"Late joining as ID: {jobId}");
                 _consoleHost.ExecuteCommand($"joingame {CommandParsing.Escape(jobId)} {station}");
                 Close();
             };
 
             _gameTicker.LobbyJobsAvailableUpdated += JobsAvailableUpdated;
+            _gameTicker.PlayerFactionCountsUpdated += OnPlayerFactionCountsUpdated;
         }
 
         private void RebuildUI()
@@ -82,7 +84,7 @@ private void RebuildUI()
             _jobCategories.Clear();
 
             if (!_gameTicker.DisallowedLateJoin && _gameTicker.StationNames.Count == 0)
-                Logger.Warning("No stations exist, nothing to display in late-join GUI");
+                _sawmill.Warning("No stations exist, nothing to display in late-join GUI");
 
             foreach (var (id, name) in _gameTicker.StationNames)
             {
@@ -208,7 +210,21 @@ private void RebuildUI()
                             MinSize = new Vector2(0, 23),
                         });
                     }
-
+                    var currentFactionPlayers = 0;
+                    var currentText = departmentName;
+                    var currentcount = _gameTicker.PlayerFactionCounts;
+                    foreach (var faction in currentcount)
+                    {
+                        if (faction.Key == departmentName)
+                        {
+                            currentFactionPlayers = faction.Value;
+                            break;
+                        }
+                    }
+                    if (currentFactionPlayers > 0)
+                    {
+                        currentText = $"{departmentName} ({currentFactionPlayers} players)";
+                    }
                     category.AddChild(new PanelContainer
                     {
                         Children =
@@ -216,7 +232,7 @@ private void RebuildUI()
                             new Label
                             {
                                 StyleClasses = { "LabelBig" },
-                                Text = Loc.GetString("late-join-gui-department-jobs-label", ("departmentName", departmentName))
+                                Text = currentText
                             }
                         }
                     });
@@ -320,7 +336,11 @@ private void JobsAvailableUpdated(IReadOnlyDictionary<NetEntity, Dictionary<Prot
                 }
             }
         }
-
+        private void OnPlayerFactionCountsUpdated()
+        {
+            RebuildUI(); // Rebuild the UI to reflect new faction counts
+        }
+        [Obsolete("Overrides obsolete member 'Control.Dispose(bool)'.")]
         protected override void Dispose(bool disposing)
         {
             base.Dispose(disposing);
@@ -329,6 +349,7 @@ protected override void Dispose(bool disposing)
             {
                 _jobRequirements.Updated -= RebuildUI;
                 _gameTicker.LobbyJobsAvailableUpdated -= JobsAvailableUpdated;
+                _gameTicker.PlayerFactionCountsUpdated -= OnPlayerFactionCountsUpdated;
                 _jobButtons.Clear();
                 _jobCategories.Clear();
             }

+ 6 - 6
Content.Client/RoundEnd/RoundEndSummaryWindow.cs

@@ -127,12 +127,12 @@ private BoxContainer MakePlayerManifestTab(RoundEndMessageEvent.RoundEndPlayerIn
                 if (playerInfo.PlayerNetEntity != null)
                 {
                     hBox.AddChild(new SpriteView(playerInfo.PlayerNetEntity.Value, _entityManager)
-                        {
-                            OverrideDirection = Direction.South,
-                            VerticalAlignment = VAlignment.Center,
-                            SetSize = new Vector2(32, 32),
-                            VerticalExpand = true,
-                        });
+                    {
+                        OverrideDirection = Direction.South,
+                        VerticalAlignment = VAlignment.Center,
+                        SetSize = new Vector2(32, 32),
+                        VerticalExpand = true,
+                    });
                 }
 
                 if (playerInfo.PlayerICName != null)

+ 2 - 2
Content.Client/StatusIcon/StatusIconSystem.cs

@@ -89,8 +89,8 @@ public bool IsVisible(Entity<MetaDataComponent> ent, StatusIconData data)
         if (TryComp<SpriteComponent>(ent, out var sprite) && !sprite.Visible)
             return false;
 
-        if (data.ShowTo != null && !_entityWhitelist.IsValid(data.ShowTo, viewer))
-            return false;
+        //if (data.ShowTo != null && !_entityWhitelist.IsValid(data.ShowTo, viewer))
+        //    return false;
 
         return true;
     }

+ 36 - 36
Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs

@@ -76,7 +76,7 @@ private void UpdateOverlays(EntityUid entity, MobStateComponent? mobState, Damag
     {
         if (mobState == null && !EntityManager.TryGetComponent(entity, out mobState) ||
             thresholds == null && !EntityManager.TryGetComponent(entity, out thresholds) ||
-            damageable == null && !EntityManager.TryGetComponent(entity, out  damageable))
+            damageable == null && !EntityManager.TryGetComponent(entity, out damageable))
             return;
 
         if (!_mobThresholdSystem.TryGetIncapThreshold(entity, out var foundThreshold, thresholds))
@@ -94,51 +94,51 @@ private void UpdateOverlays(EntityUid entity, MobStateComponent? mobState, Damag
         switch (mobState.CurrentState)
         {
             case MobState.Alive:
-            {
-                FixedPoint2 painLevel = 0;
-                _overlay.PainLevel = 0;
-
-                if (!EntityManager.HasComponent<PainNumbnessComponent>(entity))
                 {
-                    foreach (var painDamageType in damageable.PainDamageGroups)
+                    FixedPoint2 painLevel = 0;
+                    _overlay.PainLevel = 0;
+
+                    if (!EntityManager.HasComponent<PainNumbnessComponent>(entity))
                     {
-                        damageable.DamagePerGroup.TryGetValue(painDamageType, out var painDamage);
-                        painLevel += painDamage;
+                        foreach (var painDamageType in damageable.PainDamageGroups)
+                        {
+                            damageable.DamagePerGroup.TryGetValue(painDamageType, out var painDamage);
+                            painLevel += painDamage;
+                        }
+                        _overlay.PainLevel = FixedPoint2.Min(1f, painLevel / critThreshold).Float();
+
+                        if (_overlay.PainLevel < 0.05f) // Don't show damage overlay if they're near enough to max.
+                        {
+                            _overlay.PainLevel = 0;
+                        }
                     }
-                    _overlay.PainLevel = FixedPoint2.Min(1f, painLevel / critThreshold).Float();
 
-                    if (_overlay.PainLevel < 0.05f) // Don't show damage overlay if they're near enough to max.
+                    if (damageable.DamagePerGroup.TryGetValue("Airloss", out var oxyDamage))
                     {
-                        _overlay.PainLevel = 0;
+                        _overlay.OxygenLevel = FixedPoint2.Min(1f, oxyDamage / critThreshold).Float();
                     }
-                }
 
-                if (damageable.DamagePerGroup.TryGetValue("Airloss", out var oxyDamage))
-                {
-                    _overlay.OxygenLevel = FixedPoint2.Min(1f, oxyDamage / critThreshold).Float();
+                    _overlay.CritLevel = 0;
+                    _overlay.DeadLevel = 0;
+                    break;
                 }
-
-                _overlay.CritLevel = 0;
-                _overlay.DeadLevel = 0;
-                break;
-            }
             case MobState.Critical:
-            {
-                if (!_mobThresholdSystem.TryGetDeadPercentage(entity,
-                        FixedPoint2.Max(0.0, damageable.TotalDamage), out var critLevel))
-                    return;
-                _overlay.CritLevel = critLevel.Value.Float();
-
-                _overlay.PainLevel = 0;
-                _overlay.DeadLevel = 0;
-                break;
-            }
+                {
+                    if (!_mobThresholdSystem.TryGetDeadPercentage(entity,
+                            FixedPoint2.Max(0.0, damageable.TotalDamage), out var critLevel))
+                        return;
+                    _overlay.CritLevel = critLevel.Value.Float();
+
+                    _overlay.PainLevel = 0;
+                    _overlay.DeadLevel = 0;
+                    break;
+                }
             case MobState.Dead:
-            {
-                _overlay.PainLevel = 0;
-                _overlay.CritLevel = 0;
-                break;
-            }
+                {
+                    _overlay.PainLevel = 0;
+                    _overlay.CritLevel = 0;
+                    break;
+                }
         }
     }
 }

+ 21 - 4
Content.Server/Atmos/Rotting/RottingSystem.cs

@@ -7,16 +7,18 @@
 using Robust.Server.Containers;
 using Robust.Shared.Physics.Components;
 using Robust.Shared.Timing;
+using Content.Server.GameTicking;
+using Content.Server.GameTicking.Rules.Components;
+using Content.Shared.GameTicking.Components;
 
 namespace Content.Server.Atmos.Rotting;
-
 public sealed class RottingSystem : SharedRottingSystem
 {
     [Dependency] private readonly IGameTiming _timing = default!;
     [Dependency] private readonly AtmosphereSystem _atmosphere = default!;
     [Dependency] private readonly ContainerSystem _container = default!;
     [Dependency] private readonly DamageableSystem _damageable = default!;
-
+    [Dependency] private readonly GameTicker _gameTicker = default!;
     public override void Initialize()
     {
         base.Initialize();
@@ -108,11 +110,26 @@ public override void Update(float frameTime)
                 var damage = rotting.Damage * rotting.RotUpdateRate.TotalSeconds;
                 _damageable.TryChangeDamage(uid, damage, true, false);
             }
-
             if (TryComp<RotIntoComponent>(uid, out var rotInto))
             {
+                var rotStageEnd = rotInto.Stage;
+                //on tdm, faster rotting
+                var query = EntityQueryEnumerator<TeamDeathMatchRuleComponent, GameRuleComponent>();
+                while (query.MoveNext(out var nuid, out var tdm, out var gameRule))
+                {
+                    if (_gameTicker.IsGameRuleActive(nuid, gameRule))
+                    {
+
+                        if (perishable.RotAccumulator.TotalSeconds >= 300)
+                        {
+                            Spawn(rotInto.Entity, xform.Coordinates);
+                            QueueDel(uid);
+                            return;
+                        }
+                    }
+                }
                 var stage = RotStage(uid, rotting, perishable);
-                if (stage >= rotInto.Stage)
+                if (stage >= rotStageEnd)
                 {
                     Spawn(rotInto.Entity, xform.Coordinates);
                     QueueDel(uid);

+ 3 - 1
Content.Server/GameTicking/GameTicker.GameRule.cs

@@ -354,8 +354,10 @@ private void AddGameRuleCommand(IConsoleShell shell, string argstr, string[] arg
             var ent = AddGameRule(rule);
 
             // Start rule if we're already in the middle of a round
-            if(RunLevel == GameRunLevel.InRound)
+            if (RunLevel == GameRunLevel.InRound)
+            {
                 StartGameRule(ent);
+            }
 
         }
     }

+ 33 - 3
Content.Server/GameTicking/GameTicker.Lobby.cs

@@ -4,7 +4,9 @@
 using Robust.Shared.Network;
 using Robust.Shared.Player;
 using System.Text;
-
+using Content.Shared.NPC.Prototypes;
+using Robust.Shared.Prototypes;
+using Content.Shared.NPC.Components;
 namespace Content.Server.GameTicking
 {
     public sealed partial class GameTicker
@@ -38,6 +40,7 @@ public sealed partial class GameTicker
         public void UpdateInfoText()
         {
             RaiseNetworkEvent(GetInfoMsg(), Filter.Empty().AddPlayers(_playerManager.NetworkedSessions));
+            RaiseNetworkEvent(GetPlayerCountsMsg(), Filter.Empty().AddPlayers(_playerManager.NetworkedSessions)); // Send faction counts too
         }
 
         private string GetInfoText()
@@ -61,7 +64,7 @@ private string GetInfoText()
             {
                 foundOne = true;
                 if (stationNames.Length > 0)
-                        stationNames.Append('\n');
+                    stationNames.Append('\n');
 
                 stationNames.Append(meta.EntityName);
             }
@@ -107,9 +110,13 @@ private void SendStatusToAll()
 
         private TickerLobbyInfoEvent GetInfoMsg()
         {
-            return new (GetInfoText());
+            return new(GetInfoText());
         }
 
+        private GetPlayerFactionCounts GetPlayerCountsMsg()
+        {
+            return new(GetPlayerFactionCounts());
+        }
         private void UpdateLateJoinStatus()
         {
             RaiseNetworkEvent(new TickerLateJoinStatusEvent(DisallowLateJoin));
@@ -179,7 +186,30 @@ public void ToggleReady(ICommonSession player, bool ready)
             // update server info to reflect new ready count
             UpdateInfoText();
         }
+        public Dictionary<ProtoId<NpcFactionPrototype>, int> GetPlayerFactionCounts()
+        {
+            var factionCounts = new Dictionary<ProtoId<NpcFactionPrototype>, int>();
 
+            // Iterate through all currently connected player sessions on the server
+            foreach (var session in _playerManager.Sessions)
+            {
+                // Get the entity currently controlled by the player
+                if (session.AttachedEntity is not { Valid: true } playerEntity)
+                    continue;
+
+                // Try to get the NpcFactionMemberComponent from the player's controlled entity
+                if (TryComp<NpcFactionMemberComponent>(playerEntity, out var factionMemberComponent))
+                {
+                    // A player can be part of multiple factions
+                    foreach (var factionId in factionMemberComponent.Factions)
+                    {
+                        factionCounts.TryGetValue(factionId, out var currentCount);
+                        factionCounts[factionId] = currentCount + 1;
+                    }
+                }
+            }
+            return factionCounts;
+        }
         public bool UserHasJoinedGame(ICommonSession session)
             => UserHasJoinedGame(session.UserId);
 

+ 51 - 2
Content.Server/GameTicking/GameTicker.Spawning.cs

@@ -21,6 +21,9 @@
 using Robust.Shared.Prototypes;
 using Robust.Shared.Random;
 using Robust.Shared.Utility;
+using Robust.Shared.Timing;
+using Content.Server.GameTicking.Rules.Components;
+using Content.Shared.GameTicking.Components;
 
 namespace Content.Server.GameTicking
 {
@@ -149,9 +152,55 @@ private List<EntityUid> GetSpawnableStations()
                     return;
             }
 
+            foreach (var tracker in EntityQuery<RespawnTrackerComponent>())
+            {
+                foreach (var (player1, time) in tracker.RespawnQueue)
+                {
+                    if (player1 == player.UserId)
+                    {
+                        if (_gameTiming.CurTime < time)
+                        {
+                            _chatManager.DispatchServerMessage(player,
+                                Loc.GetString("rule-respawn-blocked", ("seconds", time.TotalSeconds - _gameTiming.CurTime.TotalSeconds)));
+                            return;
+                        }
+                    }
+                }
+            }
+            //if TDM, check if the teams are balanced
+            var factionCount = GetPlayerFactionCounts();
+            if (factionCount != null && factionCount.Count > 1)
+            {
+                //get the faction of the selected job
+                if (jobId != null && _prototypeManager.TryIndex<JobPrototype>(jobId, out var job))
+                {
+                    var selectedFaction = job.Faction;
+                    var currentCount = 0;
+                    var minCount = 1000;
+                    foreach (var fact in factionCount)
+                    {
+                        if (fact.Key == selectedFaction)
+                        {
+                            currentCount = fact.Value;
+
+                        }
+                        else if (fact.Key != selectedFaction && fact.Value < minCount)
+                        {
+                            minCount = fact.Value;
+                        }
+                    }
+                    if (currentCount > minCount)
+                    {
+                        //if the current faction is greater than the minimum faction, block the respawn
+                        _chatManager.DispatchServerMessage(player,
+                            Loc.GetString("rule-respawn-autobalance", ("this", currentCount), ("other", minCount)));
+                        return;
+                    }
+                }
+
+            }
             SpawnPlayer(player, character, station, jobId, lateJoin, silent);
         }
-
         private void SpawnPlayer(ICommonSession player,
             HumanoidCharacterProfile character,
             EntityUid station,
@@ -430,7 +479,7 @@ public EntityCoordinates GetObserverSpawnPoint()
                 // Ideally engine would just spawn them on grid directly I guess? Right now grid traversal is handling it during
                 // update which means we need to add a hack somewhere around it.
                 var spawn = _robustRandom.Pick(_possiblePositions);
-                var toMap = spawn.ToMap(EntityManager, _transform);
+                var toMap = _transform.ToMapCoordinates(spawn);
 
                 if (_mapManager.TryFindGridAt(toMap, out var gridUid, out _))
                 {

+ 14 - 8
Content.Server/GameTicking/Rules/CaptureAreaSystem.cs

@@ -5,7 +5,8 @@
 using Robust.Shared.Timing;
 using Content.Server.Chat.Systems;
 using Content.Server.RoundEnd;
-
+using Content.Shared.Mobs.Components;
+using Content.Shared.Mobs;
 namespace Content.Server.GameTicking.Rules;
 
 public sealed class CaptureAreaSystem : GameRuleSystem<CaptureAreaRuleComponent>
@@ -47,14 +48,19 @@ private void ProcessArea(EntityUid uid, CaptureAreaComponent area, float frameTi
         var entitiesInRange = _lookup.GetEntitiesInRange(areaXform, area.CaptureRadius, LookupFlags.Dynamic | LookupFlags.Sundries); // Include dynamic entities and items/mobs etc.
         foreach (var entity in entitiesInRange)
         {
-            // Check if the entity has a faction and if it's one we care about
-            if (_entityManager.TryGetComponent<NpcFactionMemberComponent>(entity, out var factionMember))
+            if (EntityManager.TryGetComponent<MobStateComponent>(entity, out var mobState))
             {
-                foreach (var faction in factionMember.Factions)
-                {
-                    if (area.CapturableFactions.Contains(faction))
-                        factionCounts[faction]++;
-                }
+                //do not count dead and crit mobs
+                if (mobState.CurrentState == MobState.Alive)
+                    // Check if the entity has a faction and if it's one we care about
+                    if (_entityManager.TryGetComponent<NpcFactionMemberComponent>(entity, out var factionMember))
+                    {
+                        foreach (var faction in factionMember.Factions)
+                        {
+                            if (area.CapturableFactions.Contains(faction))
+                                factionCounts[faction]++;
+                        }
+                    }
             }
         }
 

+ 40 - 0
Content.Server/GameTicking/Rules/Components/TeamDeathMatchRuleComponent.cs

@@ -0,0 +1,40 @@
+using Content.Shared.FixedPoint;
+using Content.Shared.Roles;
+using Content.Shared.Storage;
+using Robust.Shared.Network;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
+
+namespace Content.Server.GameTicking.Rules.Components;
+
+/// <summary>
+/// Gamerule that tracks stats for TDM gamemodes
+/// </summary>
+[RegisterComponent, Access(typeof(TeamDeathMatchRuleSystem))]
+public sealed partial class TeamDeathMatchRuleComponent : Component
+{
+
+    [DataField("team1")]
+    public string Team1 = "";
+
+    [DataField("team1Points")]
+    public int Team1Points = 0;
+
+    [DataField("team1Deaths")]
+    public int Team1Deaths = 0;
+
+    [DataField("team1Kills")]
+    public int Team1Kills = 0;
+
+    [DataField("team2")]
+    public string Team2 = "";
+
+    [DataField("team2Points")]
+    public int Team2Points = 0;
+
+    [DataField("team2Deaths")]
+    public int Team2Deaths = 0;
+
+    [DataField("team2Kills")]
+    public int Team2Kills = 0;
+}

+ 7 - 6
Content.Server/GameTicking/Rules/RespawnRuleSystem.cs

@@ -51,10 +51,11 @@ public override void Update(float frameTime)
 
                 if (!_playerManager.TryGetSessionById(player, out var session))
                     continue;
-
-                if (session.GetMind() is { } mind && TryComp<MindComponent>(mind, out var mindComp) && mindComp.OwnedEntity.HasValue)
-                    QueueDel(mindComp.OwnedEntity.Value);
-                GameTicker.MakeJoinGame(session, station, silent: true);
+                //This autorespawner is disabled since people can manually return to the lobby.
+                //We just check on the spawn event if the player is not in the queue.
+                //if (session.GetMind() is { } mind && TryComp<MindComponent>(mind, out var mindComp) && mindComp.OwnedEntity.HasValue)
+                //    QueueDel(mindComp.OwnedEntity.Value);
+                //GameTicker.MakeJoinGame(session, station, silent: true);
                 tracker.RespawnQueue.Remove(player);
             }
         }
@@ -63,7 +64,7 @@ public override void Update(float frameTime)
     private void OnSuicide(SuicideEvent ev)
     {
         if (!TryComp<ActorComponent>(ev.Victim, out var actor))
-           return;
+            return;
 
         var query = EntityQueryEnumerator<RespawnTrackerComponent>();
         while (query.MoveNext(out _, out var respawn))
@@ -82,7 +83,7 @@ private void OnMobStateChanged(MobStateChangedEvent args)
             return;
 
         var query = EntityQueryEnumerator<RespawnDeadRuleComponent, RespawnTrackerComponent, GameRuleComponent>();
-        while (query.MoveNext(out var uid, out var respawnRule, out  var tracker, out var rule))
+        while (query.MoveNext(out var uid, out var respawnRule, out var tracker, out var rule))
         {
             if (!GameTicker.IsGameRuleActive(uid, rule))
                 continue;

+ 149 - 0
Content.Server/GameTicking/Rules/TeamDeathMatchRuleSystem.cs

@@ -0,0 +1,149 @@
+using System.Linq;
+using Content.Server.Administration.Commands;
+using Content.Server.GameTicking.Rules.Components;
+using Content.Server.KillTracking;
+using Content.Server.Mind;
+using Content.Server.Points;
+using Content.Server.RoundEnd;
+using Content.Server.Station.Systems;
+using Content.Server.NPC.Systems;
+using Content.Shared.GameTicking;
+using Content.Shared.GameTicking.Components;
+using Content.Shared.NPC.Components;
+using Content.Shared.Points;
+using Content.Shared.Storage;
+using Robust.Server.GameObjects;
+using Robust.Server.Player;
+using Robust.Shared.Utility;
+using Content.Shared.NPC.Systems;
+
+namespace Content.Server.GameTicking.Rules;
+
+/// <summary>
+/// Manages <see cref="TeamDeathMatchRuleComponent"/>
+/// </summary>
+public sealed class TeamDeathMatchRuleSystem : GameRuleSystem<TeamDeathMatchRuleComponent>
+{
+    [Dependency] private readonly IPlayerManager _player = default!;
+    [Dependency] private readonly MindSystem _mind = default!;
+    [Dependency] private readonly PointSystem _point = default!;
+    [Dependency] private readonly RespawnRuleSystem _respawn = default!;
+    [Dependency] private readonly RoundEndSystem _roundEnd = default!;
+    [Dependency] private readonly StationSpawningSystem _stationSpawning = default!;
+    [Dependency] private readonly NpcFactionSystem _factionSystem = default!; // Added dependency
+    [Dependency] private readonly TransformSystem _transform = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<PlayerBeforeSpawnEvent>(OnBeforeSpawn);
+        SubscribeLocalEvent<PlayerSpawnCompleteEvent>(OnSpawnComplete);
+        SubscribeLocalEvent<KillReportedEvent>(OnKillReported);
+    }
+
+    private void OnBeforeSpawn(PlayerBeforeSpawnEvent ev)
+    {
+        var query = EntityQueryEnumerator<TeamDeathMatchRuleComponent, RespawnTrackerComponent, GameRuleComponent>();
+        while (query.MoveNext(out var uid, out var dm, out var tracker, out var rule))
+        {
+            if (!GameTicker.IsGameRuleActive(uid, rule))
+                continue;
+
+            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);
+            DebugTools.AssertNotNull(mobMaybe);
+            var mob = mobMaybe!.Value;
+
+            _mind.TransferTo(newMind, mob);
+            EnsureComp<KillTrackerComponent>(mob);
+
+            ev.Handled = true;
+            break;
+        }
+    }
+
+    private void OnSpawnComplete(PlayerSpawnCompleteEvent ev)
+    {
+        EnsureComp<KillTrackerComponent>(ev.Mob);
+        var query = EntityQueryEnumerator<TeamDeathMatchRuleComponent, GameRuleComponent>();
+        while (query.MoveNext(out var uid, out var component, out var rule))
+        {
+            if (!GameTicker.IsGameRuleActive(uid, rule))
+                continue;
+            if (component.Team1 == "")
+            {
+                if (TryComp<NpcFactionMemberComponent>(ev.Mob, out var npc))
+                {
+                    if (npc.Factions.Count > 0 && npc.Factions.First() != component.Team2)
+                    {
+                        component.Team1 = npc.Factions.First();
+                    }
+                }
+            }
+            if (component.Team2 == "")
+            {
+                if (TryComp<NpcFactionMemberComponent>(ev.Mob, out var npc))
+                {
+                    if (npc.Factions.Count > 0 && npc.Factions.First() != component.Team1)
+                    {
+                        component.Team2 = npc.Factions.First();
+                    }
+                }
+            }
+        }
+    }
+
+    private void OnKillReported(ref KillReportedEvent ev)
+    {
+        var query = EntityQueryEnumerator<TeamDeathMatchRuleComponent, GameRuleComponent>();
+        while (query.MoveNext(out var uid, out var dm, out var rule))
+        {
+            if (!GameTicker.IsGameRuleActive(uid, rule))
+                continue;
+
+            // Check if the killed entity is part of either team using FactionSystem
+            // This avoids potential direct access permission issues with NpcFactionMemberComponent.Factions
+            if (HasComp<NpcFactionMemberComponent>(ev.Entity)) // Ensure the component exists before checking factions
+            {
+                if (_factionSystem.IsMember(ev.Entity, dm.Team1))
+                {
+                    dm.Team1Deaths += 1;
+                    dm.Team2Kills += 1;
+                }
+                else if (_factionSystem.IsMember(ev.Entity, dm.Team2))
+                {
+                    dm.Team2Deaths += 1;
+                    dm.Team1Kills += 1;
+                }
+            }
+        }
+    }
+
+    protected override void AppendRoundEndText(EntityUid uid, TeamDeathMatchRuleComponent component, GameRuleComponent gameRule, ref RoundEndTextAppendEvent args)
+    {
+        // If we are using points, use them to display winner
+        if (component.Team1Points > 0 && component.Team2Points > 0)
+        {
+            if (component.Team1Points > component.Team2Points)
+            {
+                args.AddLine($"[color=lime]{component.Team1}[/color] has won!");
+            }
+            else if (component.Team1Points < component.Team2Points)
+            {
+                args.AddLine($"[color=lime]{component.Team2}[/color] has won!");
+
+            }
+            else
+            {
+                args.AddLine("The round ended in a [color=yellow]draw[/color]!");
+            }
+        }
+        args.AddLine("");
+        args.AddLine($"[color=cyan]{component.Team1}[/color]: {component.Team1Kills} Kills, {component.Team1Deaths} Deaths");
+        args.AddLine("");
+        args.AddLine($"[color=cyan]{component.Team2}[/color]: {component.Team2Kills} Kills, {component.Team2Deaths} Deaths");
+    }
+}

+ 1 - 2
Content.Shared/Atmos/Rotting/SharedRottingSystem.cs

@@ -35,7 +35,6 @@ private void OnPerishableMapInit(EntityUid uid, PerishableComponent component, M
     {
         component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate;
     }
-
     private void OnMobStateChanged(EntityUid uid, PerishableComponent component, MobStateChangedEvent args)
     {
         if (args.NewMobState != MobState.Dead && args.OldMobState != MobState.Dead)
@@ -170,6 +169,6 @@ public int RotStage(EntityUid uid, RottingComponent? comp = null, PerishableComp
         if (!Resolve(uid, ref comp, ref perishable))
             return 0;
 
-        return (int) (comp.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds);
+        return (int)(comp.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds);
     }
 }

+ 13 - 0
Content.Shared/GameTicking/SharedGameTicker.cs

@@ -7,6 +7,8 @@
 using Robust.Shared.Serialization.Markdown.Value;
 using Robust.Shared.Timing;
 using Robust.Shared.Audio;
+using Robust.Shared.Player;
+using Content.Shared.NPC.Prototypes;
 
 namespace Content.Shared.GameTicking
 {
@@ -14,6 +16,7 @@ public abstract class SharedGameTicker : EntitySystem
     {
         [Dependency] private readonly IReplayRecordingManager _replay = default!;
         [Dependency] private readonly IGameTiming _gameTiming = default!;
+        [Dependency] private readonly ISharedPlayerManager _playerManager = default!;
 
         // See ideally these would be pulled from the job definition or something.
         // But this is easier, and at least it isn't hardcoded.
@@ -119,6 +122,16 @@ public TickerLobbyInfoEvent(string textBlob)
         }
     }
 
+    [Serializable, NetSerializable]
+    public sealed class GetPlayerFactionCounts : EntityEventArgs
+    {
+        public Dictionary<ProtoId<NpcFactionPrototype>, int> FactionCounts { get; } = new();
+
+        public GetPlayerFactionCounts(Dictionary<ProtoId<NpcFactionPrototype>, int> factionCounts)
+        {
+            FactionCounts = factionCounts;
+        }
+    }
     [Serializable, NetSerializable]
     public sealed class TickerLobbyCountdownEvent : EntityEventArgs
     {

+ 41 - 1
Content.Shared/Projectiles/SharedProjectileSystem.cs

@@ -41,6 +41,8 @@ public abstract partial class SharedProjectileSystem : EntitySystem
     [Dependency] private readonly SharedGunSystem _guns = default!;
     [Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!;
     [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly ILogManager _log = default!;
+    private ISawmill _sawmill = default!;
     public override void Initialize()
     {
         base.Initialize();
@@ -51,6 +53,7 @@ public override void Initialize()
         SubscribeLocalEvent<EmbeddableProjectileComponent, ThrowDoHitEvent>(OnEmbedThrowDoHit);
         SubscribeLocalEvent<EmbeddableProjectileComponent, ActivateInWorldEvent>(OnEmbedActivate);
         SubscribeLocalEvent<EmbeddableProjectileComponent, RemoveEmbeddedProjectileEvent>(OnEmbedRemove);
+        _sawmill = _log.GetSawmill("projectile");
     }
 
     private void OnStartCollide(EntityUid uid, ProjectileComponent component, ref StartCollideEvent args)
@@ -251,10 +254,47 @@ private void PreventCollision(EntityUid uid, ProjectileComponent component, ref
         //check for barricade component (percentage of chance to hit/pass over)
         if (TryComp(args.OtherEntity, out BarricadeComponent? barricade))
         {
-            if (_random.NextFloat(0.0f, 100.0f) <= barricade.Blocking)
+            var alwaysPassThrough = false;
+            _sawmill.Info("Checking barricade...");
+            if (component.Shooter is { } shooterUid && Exists(shooterUid))
+            {
+                // Condition 1: Directions are the same (using cardinal directions).
+                var shooterWorldRotation = _transform.GetWorldRotation(shooterUid);
+                var barricadeWorldRotation = _transform.GetWorldRotation(args.OtherEntity);
+
+                var shooterDir = shooterWorldRotation.GetCardinalDir();
+                var barricadeDir = barricadeWorldRotation.GetCardinalDir();
+
+                if (shooterDir == barricadeDir)
+                {
+
+                    _sawmill.Info("Same dir!");
+                    // Condition 2: Firer is within 1 tile of the barricade.
+                    var shooterCoords = Transform(shooterUid).Coordinates;
+                    var barricadeCoords = Transform(args.OtherEntity).Coordinates;
+
+                    if (shooterCoords.TryDistance(EntityManager, barricadeCoords, out var distance) &&
+                        distance <= 1.3f)
+                    {
+                        _sawmill.Info($"Distance: {distance}");
+                        alwaysPassThrough = true;
+                    }
+                }
+            }
+
+            if (alwaysPassThrough)
             {
                 args.Cancelled = true;
             }
+            else
+            {
+                _sawmill.Info("Not same dir or too far away!");
+                // Standard barricade blocking logic if the special conditions are not met.
+                if (_random.NextFloat(0.0f, 100.0f) >= barricade.Blocking)
+                {
+                    args.Cancelled = true;
+                }
+            }
         }
     }
 

+ 3 - 0
Resources/Locale/en-US/game-ticking/game-rules/rules.ftl

@@ -4,3 +4,6 @@ rule-time-has-run-out = Time has run out!
 
 # Respawning
 rule-respawn-in-seconds = Respawning in {$second} seconds...
+rule-respawn-blocked = You cannot join yet, please wait {$seconds} seconds.
+rule-respawn-autobalance = There are too many players in the selected faction! It has {$this} active players and there is a faction with only {$other}.
+

+ 2 - 2
Resources/Locale/en-US/game-ticking/game-ticker.ftl

@@ -13,7 +13,7 @@ game-ticker-get-info-text = Hi and welcome to [color=white]Civilization 14![/col
                             The current player count is: [color=white]{$playerCount}[/color]
                             The current map is: [color=white]{$mapName}[/color]
                             The current game mode is: [color=white]{$gmTitle}[/color]
-                            >[color=yellow]{$desc}[/color]
+                            - [color=yellow]{$desc}[/color]
 game-ticker-get-info-preround-text = Hi and welcome to [color=white]Civilization 14![/color]
                             The current round is: [color=white]#{$roundId}[/color]
                             The current player count is: [color=white]{$playerCount}[/color] ([color=white]{$readyCount}[/color] {$readyCount ->
@@ -22,7 +22,7 @@ game-ticker-get-info-preround-text = Hi and welcome to [color=white]Civilization
                             } ready)
                             The current map is: [color=white]{$mapName}[/color]
                             The current game mode is: [color=white]{$gmTitle}[/color]
-                            >[color=yellow]{$desc}[/color]
+                            - [color=yellow]{$desc}[/color]
 game-ticker-no-map-selected = [color=yellow]Map not yet selected![/color]
 game-ticker-player-no-jobs-available-when-joining = When attempting to join to the game, no jobs were available.
 

+ 2 - 2
Resources/Locale/en-US/job/department.ftl

@@ -10,5 +10,5 @@ department-Silicon = Silicon
 department-Specific = Station specific
 
 department-Nomads = Nomads
-department-French = French
-department-English = English
+department-French = France
+department-English = England

+ 3 - 3
Resources/Locale/en-US/late-join/late-join-gui.ftl

@@ -1,6 +1,6 @@
-late-join-gui-title = Late Join
-late-join-gui-jobs-amount-in-department-tooltip = Jobs in the {$departmentName} department
-late-join-gui-department-jobs-label = {$departmentName} jobs
+late-join-gui-title = Join Game
+late-join-gui-jobs-amount-in-department-tooltip = Jobs in the {$departmentName} faction
+late-join-gui-department-jobs-label = {$departmentName} roles
 late-join-gui-job-slot-capped = {$originalName} ({$jobName}) ({$amount} open)
 late-join-gui-job-slot-uncapped = {$originalName} ({$jobName}) (∞ open)
 late-join-gui-job-slot-capped-no-original = {$jobName} ({$amount} open)

Diff do ficheiro suprimidas por serem muito extensas
+ 2 - 2
Resources/Maps/civ/tdm/camp.yml


+ 28 - 16
Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_hats.yml

@@ -2282,6 +2282,8 @@
       sprite: Civ14/Clothing/exported/hats/bascinet_o.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/hats/bascinet_o.rsi
+    - type: STWeight
+      self: 8
     - type: Armor
       modifiers:
         coefficients:
@@ -2306,13 +2308,15 @@
       sprite: Civ14/Clothing/exported/hats/knight_simple.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/hats/knight_simple.rsi
+    - type: STWeight
+      self: 8
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.30
-          Slash: 0.30
+          Blunt: 0.70
+          Slash: 0.70
           Piercing: 0.9
-          Arrow: 0.1
+          Arrow: 0.5
           Heat: 0.85
 - type: entity
   name: protective conical helmet
@@ -2324,13 +2328,15 @@
       sprite: Civ14/Clothing/exported/hats/medieval_helmet1.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/hats/medieval_helmet1.rsi
+    - type: STWeight
+      self: 6
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.6
-          Slash: 0.6
+          Blunt: 0.8
+          Slash: 0.8
           Piercing: 0.95
-          Arrow: 0.65
+          Arrow: 0.75
           Heat: 0.85
 - type: entity
   name: kettle helmet
@@ -2342,13 +2348,15 @@
       sprite: Civ14/Clothing/exported/hats/medieval_helmet2.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/hats/medieval_helmet2.rsi
+    - type: STWeight
+      self: 5
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.6
-          Slash: 0.6
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.65
+          Arrow: 0.75
           Heat: 0.85
 - type: entity
   name: conical helmet
@@ -2360,13 +2368,15 @@
       sprite: Civ14/Clothing/exported/hats/medieval_helmet3.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/hats/medieval_helmet3.rsi
+    - type: STWeight
+      self: 5
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.65
+          Arrow: 0.75
           Heat: 0.85
 - type: entity
   name: coif wrapped mamluk helmet
@@ -2396,13 +2406,15 @@
       sprite: Civ14/Clothing/exported/hats/coif_helmet.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/hats/coif_helmet.rsi
+    - type: STWeight
+      self: 8
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
-          Piercing: 0.9
-          Arrow: 0.55
+          Blunt: 0.7
+          Slash: 0.7
+          Piercing: 0.8
+          Arrow: 0.65
           Heat: 0.85
 - type: entity
   name: purple arabic turban helmet

+ 11 - 68
Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_suit.yml

@@ -3590,7 +3590,7 @@
       time: 5
 - type: entity
   name: green plated armor
-  parent: ClothingOuterBase
+  parent: civ13_suit_plated_armor
   id: civ13_suit_green_plated_armor
   description: A thick, expensive iron armor, covering most of the body.
   components:
@@ -3598,24 +3598,10 @@
       sprite: Civ14/Clothing/exported/suits/knight_green.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/suits/knight_green.rsi
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.3
-          Slash: 0.3
-          Piercing: 0.4
-          Arrow: 0.15
-          Heat: 0.85
-    - type: Construction
-      graph: civ13_suit_green_plated_armor
-      node: end
-      cost: 5
-      material: Steel
-      time: 5
-
 - type: entity
   name: red plated armor
-  parent: ClothingOuterBase
+  parent: civ13_suit_plated_armor
+
   id: civ13_suit_red_plated_armor
   description: A thick, expensive iron armor, covering most of the body.
   components:
@@ -3623,19 +3609,10 @@
       sprite: Civ14/Clothing/exported/suits/knight_red.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/suits/knight_red.rsi
-    - type: STWeight
-      self: 25
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.3
-          Slash: 0.3
-          Piercing: 0.4
-          Arrow: 0.15
-          Heat: 0.85
 - type: entity
   name: blue plated armor
-  parent: ClothingOuterBase
+  parent: civ13_suit_plated_armor
+
   id: civ13_suit_blue_plated_armor
   description: A thick, expensive iron armor, covering most of the body.
   components:
@@ -3643,16 +3620,6 @@
       sprite: Civ14/Clothing/exported/suits/knight_blue.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/suits/knight_blue.rsi
-    - type: STWeight
-      self: 25
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.3
-          Slash: 0.3
-          Piercing: 0.4
-          Arrow: 0.15
-          Heat: 0.85
 
 - type: entity
   name: seal lifevest
@@ -4827,7 +4794,7 @@
     - type: Clothing
       sprite: Civ14/Clothing/exported/suits/knight_simple.rsi
     - type: STWeight
-      self: 25
+      self: 46
     - type: Armor
       modifiers:
         coefficients:
@@ -4870,7 +4837,7 @@
       time: 5
 - type: entity
   name: templar plated armor
-  parent: ClothingOuterBase
+  parent: civ13_suit_plated_armor
   id: civ13_suit_templar_plated_armor
   description: >-
     A thick, expensive iron armor, covering most of the body. This one is
@@ -4880,18 +4847,7 @@
       sprite: Civ14/Clothing/exported/suits/knight_templar.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/suits/knight_templar.rsi
-    - type: STWeight
-      self: 25
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.3
-          Slash: 0.3
-          Piercing: 0.4
-          Arrow: 0.15
-          Heat: 0.85
     - type: Construction
-
       graph: civ13_suit_templar_plated_armor
       node: end
       cost: 5
@@ -5133,7 +5089,7 @@
       time: 14
 - type: entity
   name: royal plated armor
-  parent: ClothingOuterBase
+  parent: civ13_suit_plated_armor
   id: civ13_suit_royal_plated_armor
   description: A thick, expensive iron armor, covering most of the body.
   components:
@@ -5141,22 +5097,11 @@
       sprite: Civ14/Clothing/exported/suits/royalplate.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/suits/royalplate.rsi
-    - type: STWeight
-      self: 25
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.15
-          Slash: 0.15
-          Piercing: 0.8
-          Arrow: 0
-          Heat: 0.85
     - type: Construction
-
       graph: civ13_suit_royal_plated_armor
       node: end
       cost: 5
-      material: Cloth
+      material: Steel
       time: 5
 - type: entity
   name: leather samurai armor
@@ -5444,7 +5389,7 @@
       material: Cloth
       time: 5
 - type: entity
-  name: plated armor
+  name: ork plated armor
   parent: ClothingOuterBase
   id: civ13_suit_plated_armor_1
   description: A cheap dark iron armor.
@@ -5465,14 +5410,13 @@
           Heat: 0.85
           Radiation: 0.55
     - type: Construction
-
       graph: civ13_suit_plated_armor_1
       node: end
       cost: 5
       material: Cloth
       time: 5
 - type: entity
-  name: plated armor
+  name: heavy ork plated armor
   parent: ClothingOuterBase
   id: civ13_suit_plated_armor_1_2
   description: A cheap dark iron armor.
@@ -5493,7 +5437,6 @@
           Heat: 0.85
           Radiation: 0.55
     - type: Construction
-
       graph: civ13_suit_plated_armor_1_2
       node: end
       cost: 5

+ 35 - 1
Resources/Prototypes/Civ14/Entities/Objects/Storage/leather.yml

@@ -27,7 +27,7 @@
       agemax: 8
 
 - type: entity
-  parent: DrinkBottleBaseEmpty
+  parent: BaseItem
   id: LeatherWaterskin
   name: leather waterskin
   description: A leather waterskin, used to carry liquids.
@@ -35,6 +35,40 @@
     - type: Sprite
       sprite: Civ14/Objects/Storage/storage.rsi
       state: waterskin
+    - type: STWeight
+      self: 2
+    - type: Item
+      size: Normal
+    - type: SolutionContainerManager
+      solutions:
+        drink:
+          maxVol: 100
+    - type: SolutionTransfer
+      canChangeTransferAmount: true
+      maxTransferAmount: 5
+    - type: Drink
+    - type: MeleeWeapon
+      soundNoDamage:
+        path: "/Audio/Effects/Fluids/splat.ogg"
+      damage:
+        types:
+          Blunt: 0
+    - type: MixableSolution
+      solution: drink
+    - type: Spillable
+      solution: drink
+    - type: FitsInDispenser
+      solution: drink
+    - type: DrawableSolution
+      solution: drink
+    - type: RefillableSolution
+      solution: drink
+    - type: DrainableSolution
+      solution: drink
+    - type: UserInterface
+      interfaces:
+        enum.TransferAmountUiKey.Key:
+          type: TransferAmountBoundUserInterface
     - type: Construction
       graph: LeatherWaterskin
       node: end

+ 9 - 9
Resources/Prototypes/Civ14/Entities/Objects/Weapons/spears.yml

@@ -8,8 +8,9 @@
   components:
     - type: Sprite
       sprite: Civ14/Weapons/assagai.rsi
-
     - type: MeleeWeapon
+      range: 2
+      attackRate: 0.8
       damage:
         types:
           Piercing: 19
@@ -30,9 +31,8 @@
   components:
     - type: Sprite
       sprite: Civ14/Weapons/dory.rsi
-
     - type: MeleeWeapon
-      range: 1.8
+      range: 2.2
       attackRate: 0.8
       damage:
         types:
@@ -59,7 +59,7 @@
 
     - type: MeleeWeapon
       attackRate: 0.6
-      range: 2.1
+      range: 2.8
       damage:
         types:
           Piercing: 16
@@ -83,9 +83,8 @@
   components:
     - type: Sprite
       sprite: Civ14/Weapons/pike.rsi
-
     - type: MeleeWeapon
-      range: 1.8
+      range: 2.2
       attackRate: 0.8
       damage:
         types:
@@ -111,9 +110,9 @@
   components:
     - type: Sprite
       sprite: Civ14/Weapons/naginata.rsi
-
     - type: MeleeWeapon
-      range: 1.6
+      range: 2.2
+      attackRate: 0.8
       damage:
         types:
           Slash: 1
@@ -140,8 +139,9 @@
   components:
     - type: Sprite
       sprite: Civ14/Weapons/halberd.rsi
-
     - type: MeleeWeapon
+      range: 2.5
+      attackRate: 0.6
       damage:
         types:
           Slash: 8

+ 11 - 1
Resources/Prototypes/Civ14/Entities/Structures/Walls/barricades.yml

@@ -35,6 +35,7 @@
     - type: Barricade
       blocking: 80
     - type: AtmosExposed
+
 - type: entity
   id: CrenelatedWallFull
   description: A stone wall with crenelations.
@@ -203,7 +204,11 @@
           behaviors:
             - !type:DoActsBehavior
               acts: ["Destruction"]
-
+    - type: Construction
+      graph: BarricadeDirtwall
+      agemin: 0
+      agemax: 8
+      node: end
 - type: entity
   id: BarricadeDirtwallMedium
   description: An unfinished dirt barricade.
@@ -259,6 +264,11 @@
           behaviors:
             - !type:DoActsBehavior
               acts: ["Destruction"]
+    - type: Construction
+      graph: BarricadeStonewall
+      agemin: 0
+      agemax: 8
+      node: end
 
 - type: entity
   id: BarricadeSandstonewall

+ 65 - 0
Resources/Prototypes/Civ14/Recipes/Construction/barricades.yml

@@ -0,0 +1,65 @@
+- type: construction
+  name: stone barricade
+  id: BarricadeStonewall
+  graph: BarricadeStonewall
+  startNode: start
+  targetNode: end
+  category: construction-category-structures
+  description: A low stone wall.
+  icon:
+    sprite: Civ14/Structures/barricades.rsi
+    state: rock_barricade
+  objectType: Structure
+  agemin: 0
+  agemax: 8
+  placementMode: SnapgridCenter
+  canBuildInImpassable: false
+  conditions:
+    - !type:TileNotBlocked
+
+- type: constructionGraph
+  id: BarricadeStonewall
+  start: start
+  graph:
+    - node: start
+      edges:
+        - to: end
+          steps:
+            - material: Stone
+              amount: 3
+              doAfter: 7
+    - node: end
+      entity: BarricadeStonewall
+
+- type: construction
+  name: dirt wall
+  id: BarricadeDirtwall
+  graph: BarricadeDirtwall
+  startNode: start
+  targetNode: end
+  category: construction-category-structures
+  description: A dirt barricade.
+  icon:
+    sprite: Civ14/Structures/barricades.rsi
+    state: dirt_wall
+  objectType: Structure
+  agemin: 0
+  agemax: 8
+  placementMode: SnapgridCenter
+  canBuildInImpassable: false
+  conditions:
+    - !type:TileNotBlocked
+
+- type: constructionGraph
+  id: BarricadeDirtwall
+  start: start
+  graph:
+    - node: start
+      edges:
+        - to: end
+          steps:
+            - material: Dirt
+              amount: 3
+              doAfter: 7
+    - node: end
+      entity: BarricadeDirtwall

+ 1 - 1
Resources/Prototypes/Civ14/Recipes/Walls/walls.yml

@@ -72,10 +72,10 @@
   agemin: 0
   agemax: 8
   placementMode: SnapgridCenter
-
   canBuildInImpassable: false
   conditions:
     - !type:TileNotBlocked
+
 - type: constructionGraph
   id: StrawWall
   start: start

+ 73 - 4
Resources/Prototypes/Civ14/StatusIcon/faction.yml

@@ -4,6 +4,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ah_basic
@@ -14,6 +15,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: arab_basic
@@ -24,6 +26,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ballas
@@ -34,6 +37,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: barbarian_basic
@@ -44,6 +48,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: blugoslavia
@@ -54,6 +59,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: brit_basic
@@ -64,6 +70,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: chechen_basic
@@ -74,6 +81,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: danish_basic
@@ -84,6 +92,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: eastern
@@ -94,16 +103,21 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: empire
 
 - type: factionIcon
-  id: EngFaction
-  priority: 1
+  id: EnglishFaction
+  priority: 0
+  locationPreference: Right
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
+      - ShowFrenchFactionIcons
+      - ShowEnglishFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: eng_basic
@@ -114,6 +128,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: finnish_basic
@@ -124,6 +139,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: fp_basic
@@ -134,16 +150,21 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: fr2_basic
 
 - type: factionIcon
-  id: FrFaction
-  priority: 1
+  id: FrenchFaction
+  priority: 0
+  locationPreference: Right
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
+      - ShowFrenchFactionIcons
+      - ShowEnglishFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: fr_basic
@@ -154,6 +175,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ger0_basic
@@ -164,6 +186,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ger2_basic
@@ -174,6 +197,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ger3_basic
@@ -184,6 +208,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ger_basic
@@ -194,6 +219,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: greek_basic
@@ -204,6 +230,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: hez_basic
@@ -214,6 +241,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ichiwa
@@ -224,6 +252,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: idf_basic
@@ -234,6 +263,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: imp_basic
@@ -244,6 +274,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ind_basic
@@ -254,6 +285,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: isis_basic
@@ -264,6 +296,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: it_basic
@@ -274,6 +307,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: jp_basic
@@ -284,6 +318,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: nl_basic
@@ -294,6 +329,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: nl_old_basic
@@ -304,6 +340,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: norway_basic
@@ -314,6 +351,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ot_basic
@@ -324,6 +362,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: pirate_basic
@@ -334,6 +373,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: police
@@ -344,6 +384,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: pol_basic
@@ -354,6 +395,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: pt2_basic
@@ -364,6 +406,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: pt_basic
@@ -374,6 +417,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: rebel_basic
@@ -384,6 +428,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: redmenia
@@ -394,6 +439,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: rednikov
@@ -404,6 +450,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: rn2_basic
@@ -414,6 +461,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: rn_basic
@@ -424,6 +472,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: robbers
@@ -434,6 +483,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: roc_basic
@@ -444,6 +494,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: roman_basic
@@ -454,6 +505,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ru_basic
@@ -464,6 +516,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: sov_basic
@@ -474,6 +527,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: spn_basic
@@ -484,6 +538,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: spr_basic
@@ -494,6 +549,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: sp_basic
@@ -504,6 +560,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: stormcloak
@@ -514,6 +571,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: swedish_basic
@@ -524,6 +582,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: syria_basic
@@ -534,6 +593,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: syria_fsa
@@ -544,6 +604,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: ukr_basic
@@ -554,6 +615,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: un
@@ -564,6 +626,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: upa_basic
@@ -574,6 +637,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: us_basic
@@ -584,6 +648,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: vc_basic
@@ -594,6 +659,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: vn_basic
@@ -604,6 +670,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: wagner
@@ -614,6 +681,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: western
@@ -624,6 +692,7 @@
   showTo:
     components:
       - ShowAntagIcons
+      - ShowFactionIcons
   icon:
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: yamaguchi

+ 12 - 0
Resources/Prototypes/GameRules/roundstart.yml

@@ -64,3 +64,15 @@
   id: CaptureAreaRule
   components:
     - type: CaptureAreaRule
+
+- type: entity
+  id: DeathMatchRule
+  parent: BaseGameRule
+  components:
+    - type: DeathMatchRule
+
+- type: entity
+  id: TeamDeathMatchRule
+  parent: BaseGameRule
+  components:
+    - type: TeamDeathMatchRule

+ 0 - 28
Resources/Prototypes/StatusIcon/faction.yml

@@ -129,31 +129,3 @@
   icon:
     sprite: /Textures/Interface/Misc/civ_hud.rsi
     state: hostile
-
-- type: factionIcon
-  id: FrenchFaction
-  priority: 0
-  locationPreference: Right
-  showTo:
-    components:
-      - ShowAntagIcons
-      - ShowFactionIcons
-      - ShowFrenchFactionIcons
-      - ShowEnglishFactionIcons
-  icon:
-    sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
-    state: fr_basic
-
-- type: factionIcon
-  id: EnglishFaction
-  priority: 0
-  locationPreference: Right
-  showTo:
-    components:
-      - ShowAntagIcons
-      - ShowFactionIcons
-      - ShowFrenchFactionIcons
-      - ShowEnglishFactionIcons
-  icon:
-    sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
-    state: eng_basic

+ 2 - 0
Resources/Prototypes/game_presets.yml

@@ -20,3 +20,5 @@
     - RespawnDeadRuleTDM
     - GracewallRule
     - CaptureAreaRule
+    - TeamDeathMatchRule
+

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff