1
0
Эх сурвалжийг харах

Tdm update 10 (#236)

* desert theme tiles, more barriers, medical loadouts

* factions

* roles and loadouts

* tdm.md

* mapping.md

* valley.md

* update valley.md

* updating valley.md

* mapping.md

* Atualizar o mapping.md

* UN Faction

* wiki stuff

* guidebooks

* Update Resources/Prototypes/game_presets.yml

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update Wiki/src/gamemodes/tdm.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* yaml fixes, spawns

* fixes, map upgrades

* palms, containers, decorative cars

* yaml typos

* tunnels

* teleporters

* WIP points system

* mechanics

* final valley tweaks

* map tweaks

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Taislin 6 сар өмнө
parent
commit
85f141ff85
100 өөрчлөгдсөн 4570 нэмэгдсэн , 1232 устгасан
  1. 1 1
      Content.Server/GameTicking/GameTicker.Spawning.cs
  2. 33 30
      Content.Server/GameTicking/Rules/CaptureAreaSystem.cs
  3. 17 0
      Content.Server/GameTicking/Rules/Components/CaptureAreaComponent.cs
  4. 20 0
      Content.Server/GameTicking/Rules/Components/ValleyCheckpointComponent.cs
  5. 164 0
      Content.Server/GameTicking/Rules/Components/ValleyPointsComponent.cs
  6. 20 0
      Content.Server/GameTicking/Rules/Components/ValleySupplyBoxComponent.cs
  7. 8 0
      Content.Server/GameTicking/Rules/TeamDeathMatchRuleSystem.cs
  8. 575 0
      Content.Server/GameTicking/Rules/ValleyPointsSystem.cs
  9. 14 0
      Content.Server/_Stalker/Teleports/LocalTeleport/LocalTeleportComponent.cs
  10. 94 0
      Content.Server/_Stalker/Teleports/LocalTeleport/LocalTeleportSystem.cs
  11. 18 5
      Content.Shared/Access/Systems/AccessReaderSystem.cs
  12. 17 0
      Content.Shared/_Stalker/Teleport/DuplicateSymbolsPrototype.cs
  13. 14 0
      Content.Shared/_Stalker/Teleport/MapLoaderPrototype.cs
  14. 33 0
      Content.Shared/_Stalker/Teleport/SharedTeleportSystem.cs
  15. 2 2
      Resources/ConfigPresets/Build/development.toml
  16. 15 1
      Resources/Locale/en-US/Civ14/jobs-descriptions.ftl
  17. 16 1
      Resources/Locale/en-US/Civ14/jobs.ftl
  18. 4 0
      Resources/Locale/en-US/game-ticking/game-presets/preset-extended.ftl
  19. 5 1
      Resources/Locale/en-US/guidebook/guides.ftl
  20. 5 0
      Resources/Locale/en-US/headset/headset-component.ftl
  21. 6 3
      Resources/Locale/en-US/job/department-desc.ftl
  22. 3 0
      Resources/Locale/en-US/job/department.ftl
  23. 79 0
      Resources/Maps/civ/tdm/valley.yml
  24. 14 10
      Resources/Prototypes/Access/command.yml
  25. 8 3
      Resources/Prototypes/Access/engineering.yml
  26. 16 16
      Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_accessories.yml
  27. 167 187
      Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_hats.yml
  28. 16 30
      Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_shoes.yml
  29. 12 0
      Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_uniform.yml
  30. 30 0
      Resources/Prototypes/Civ14/Entities/Clothing/webbings.yml
  31. 97 0
      Resources/Prototypes/Civ14/Entities/Flora/grasses.yml
  32. 75 0
      Resources/Prototypes/Civ14/Entities/Flora/warm.yml
  33. 40 69
      Resources/Prototypes/Civ14/Entities/Markers/grace_wall.yml
  34. 66 1
      Resources/Prototypes/Civ14/Entities/Markers/jobs.yml
  35. 113 0
      Resources/Prototypes/Civ14/Entities/Markers/valley_areas.yml
  36. 81 0
      Resources/Prototypes/Civ14/Entities/Mobs/NPC/civilians.yml
  37. 24 0
      Resources/Prototypes/Civ14/Entities/Objects/Radio/radio_channels.yml
  38. 25 0
      Resources/Prototypes/Civ14/Entities/Objects/Storage/filled_crates.yml
  39. 23 0
      Resources/Prototypes/Civ14/Entities/Structures/Furniture/Decorative/decoratives.yml
  40. 88 3
      Resources/Prototypes/Civ14/Entities/Structures/Walls/barricades.yml
  41. 62 0
      Resources/Prototypes/Civ14/Entities/Structures/Walls/walls.yml
  42. 19 1
      Resources/Prototypes/Civ14/Entities/Structures/wall_flags.yml
  43. 77 0
      Resources/Prototypes/Civ14/Entities/teleporters.yml
  44. 14 14
      Resources/Prototypes/Civ14/Recipes/Clothing/recipes_clothing_shoes.yml
  45. 243 0
      Resources/Prototypes/Civ14/Roles/Jobs/TDM/blugoslavia.yml
  46. 188 0
      Resources/Prototypes/Civ14/Roles/Jobs/TDM/insurgent.yml
  47. 34 0
      Resources/Prototypes/Civ14/Roles/Jobs/TDM/playtimetrackers.yml
  48. 115 0
      Resources/Prototypes/Civ14/Roles/Jobs/TDM/unitedNations.yml
  49. 32 1
      Resources/Prototypes/Civ14/Roles/Jobs/departments.yml
  50. 13 0
      Resources/Prototypes/Civ14/Roles/Jobs/jobgroups.yml
  51. 12 1
      Resources/Prototypes/Civ14/StatusIcon/faction.yml
  52. 45 0
      Resources/Prototypes/Entities/Clothing/Ears/headsets.yml
  53. 13 0
      Resources/Prototypes/Entities/Markers/Spawners/mobs.yml
  54. 48 0
      Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml
  55. 50 0
      Resources/Prototypes/Entities/Structures/Walls/asteroid.yml
  56. 42 44
      Resources/Prototypes/Entities/Structures/base_structure.yml
  57. 15 1
      Resources/Prototypes/GameRules/roundstart.yml
  58. 1 1
      Resources/Prototypes/Guidebook/nomads.yml
  59. 1 1
      Resources/Prototypes/Guidebook/rules.yml
  60. 4 4
      Resources/Prototypes/Guidebook/station.yml
  61. 13 0
      Resources/Prototypes/Guidebook/tdm.yml
  62. 32 0
      Resources/Prototypes/Maps/civ/valley.yml
  63. 4 4
      Resources/Prototypes/Tiles/floors.yml
  64. 35 0
      Resources/Prototypes/_Stalker/Entities/Objects/base.yml
  65. 123 0
      Resources/Prototypes/_Stalker/Entities/Objects/containers.yml
  66. 422 0
      Resources/Prototypes/_Stalker/Entities/Objects/transport.yml
  67. 54 0
      Resources/Prototypes/_Stalker/teleporters.yml
  68. 59 4
      Resources/Prototypes/ai_factions.yml
  69. 15 0
      Resources/Prototypes/game_presets.yml
  70. 1 10
      Resources/Prototypes/radio_channels.yml
  71. 0 191
      Resources/ServerInfo/Guidebook/Glossary.xml
  72. 29 0
      Resources/ServerInfo/Guidebook/Mapping.xml
  73. 43 0
      Resources/ServerInfo/Guidebook/TDM/tdm.xml
  74. 26 0
      Resources/ServerInfo/Guidebook/TDM/valley.xml
  75. BIN
      Resources/Textures/Civ14/Clothing/exported/ties/pasgt_un.rsi/equipped-NECK.png
  76. BIN
      Resources/Textures/Civ14/Clothing/exported/ties/pasgt_un.rsi/icon.png
  77. 23 0
      Resources/Textures/Civ14/Clothing/exported/ties/pasgt_un.rsi/meta.json
  78. BIN
      Resources/Textures/Civ14/Clothing/exported/ties/pasgt_un.rsi/pasgt_un.png
  79. BIN
      Resources/Textures/Civ14/Flora/palms.rsi/dead_palm1.png
  80. BIN
      Resources/Textures/Civ14/Flora/palms.rsi/dead_palm2.png
  81. 29 0
      Resources/Textures/Civ14/Flora/palms.rsi/meta.json
  82. BIN
      Resources/Textures/Civ14/Flora/palms.rsi/palm1.png
  83. BIN
      Resources/Textures/Civ14/Flora/palms.rsi/palm1old.png
  84. BIN
      Resources/Textures/Civ14/Flora/palms.rsi/palm2.png
  85. BIN
      Resources/Textures/Civ14/Flora/palms.rsi/palm2old.png
  86. 567 564
      Resources/Textures/Civ14/Objects/Storage/storage.rsi/meta.json
  87. BIN
      Resources/Textures/Civ14/Objects/Storage/storage.rsi/supplybox.png
  88. 4 0
      Resources/Textures/Civ14/Structures/barricades.rsi/meta.json
  89. BIN
      Resources/Textures/Civ14/Structures/barricades.rsi/sandbagfull.png
  90. BIN
      Resources/Textures/Civ14/Weapons/Guns/ak12.rsi/equipped-BACKPACK.png
  91. BIN
      Resources/Textures/Civ14/Weapons/Guns/ak12.rsi/mag-0.png
  92. 5 1
      Resources/Textures/Civ14/Weapons/Guns/ak12.rsi/meta.json
  93. BIN
      Resources/Textures/Civ14/Weapons/Guns/ak47.rsi/mag-0.png
  94. BIN
      Resources/Textures/Civ14/Weapons/Guns/ak47_magak.rsi/ak47_magak.png
  95. BIN
      Resources/Textures/Civ14/Weapons/Guns/ak47_magak.rsi/bolt-open.png
  96. BIN
      Resources/Textures/Civ14/Weapons/Guns/ak47_magak.rsi/icon.png
  97. 0 27
      Resources/Textures/Civ14/Weapons/Guns/ak47_magak.rsi/meta.json
  98. BIN
      Resources/Textures/Civ14/Weapons/Guns/ak74m.rsi/mag-0.png
  99. BIN
      Resources/Textures/Civ14/Weapons/Guns/ak74m_magak.rsi/ak74m_magak.png
  100. BIN
      Resources/Textures/Civ14/Weapons/Guns/ak74m_magak.rsi/bolt-open.png

+ 1 - 1
Content.Server/GameTicking/GameTicker.Spawning.cs

@@ -199,7 +199,7 @@ private List<EntityUid> GetSpawnableStations()
                             currentCount = fact.Value;
 
                         }
-                        else if (fact.Key != selectedFaction && fact.Value < minCount)
+                        else if (fact.Key != selectedFaction && fact.Value < minCount && fact.Key != "UnitedNations")
                         {
                             minCount = fact.Value;
                         }

+ 33 - 30
Content.Server/GameTicking/Rules/CaptureAreaSystem.cs

@@ -214,44 +214,47 @@ private void ProcessArea(EntityUid uid, CaptureAreaComponent area, float frameTi
             area.CaptureTimer += frameTime;
 
             //announce when theres 2 and 1 minutes left.
-            var timeleft = area.CaptureDuration - area.CaptureTimer;
-            if (currentController != Faction2String(ruleComp.DefenderFactionName))
+            if (ruleComp.Mode != "Points")
             {
-                if (timeleft <= 120 && area.CaptureTimerAnnouncement2 == false)
+                var timeleft = area.CaptureDuration - area.CaptureTimer;
+                if (currentController != Faction2String(ruleComp.DefenderFactionName))
                 {
-                    _chat.DispatchGlobalAnnouncement($"Two minutes until {currentController} captures {area.Name}!", "Round", false, null, Color.Blue);
-                    area.CaptureTimerAnnouncement2 = true;
-                }
-                else if (timeleft < 60 && area.CaptureTimerAnnouncement1 == false)
-                {
-                    _chat.DispatchGlobalAnnouncement($"One minute until {currentController} captures {area.Name}!", "Round", false, null, Color.Blue);
-                    area.CaptureTimerAnnouncement1 = true;
+                    if (timeleft <= 120 && area.CaptureTimerAnnouncement2 == false)
+                    {
+                        _chat.DispatchGlobalAnnouncement($"Two minutes until {currentController} captures {area.Name}!", "Round", false, null, Color.Blue);
+                        area.CaptureTimerAnnouncement2 = true;
+                    }
+                    else if (timeleft < 60 && area.CaptureTimerAnnouncement1 == false)
+                    {
+                        _chat.DispatchGlobalAnnouncement($"One minute until {currentController} captures {area.Name}!", "Round", false, null, Color.Blue);
+                        area.CaptureTimerAnnouncement1 = true;
+                    }
                 }
-            }
-            //Check for capture completion
-            if (area.CaptureTimer >= area.CaptureDuration)
-            {
-                if (_gameTicker.RunLevel == GameRunLevel.InRound)
+                //Check for capture completion
+                if (area.CaptureTimer >= area.CaptureDuration)
                 {
-                    bool canWinByCapture = true;
-                    // area.Controller is the display name of the faction that has held the point
-                    string winningControllerDisplay = area.Controller;
-
-                    if (ruleComp.Mode == "Asymmetric")
+                    if (_gameTicker.RunLevel == GameRunLevel.InRound)
                     {
-                        // In Asymmetric mode, only non-defenders (attackers) can win by capturing a point.
-                        // The defender wins by timeout.
-                        if (winningControllerDisplay == Faction2String(ruleComp.DefenderFactionName))
+                        bool canWinByCapture = true;
+                        // area.Controller is the display name of the faction that has held the point
+                        string winningControllerDisplay = area.Controller;
+
+                        if (ruleComp.Mode == "Asymmetric")
                         {
-                            canWinByCapture = false;
+                            // In Asymmetric mode, only non-defenders (attackers) can win by capturing a point.
+                            // The defender wins by timeout.
+                            if (winningControllerDisplay == Faction2String(ruleComp.DefenderFactionName))
+                            {
+                                canWinByCapture = false;
+                            }
                         }
-                    }
 
-                    if (canWinByCapture && !string.IsNullOrEmpty(winningControllerDisplay))
-                    {
-                        _chat.DispatchGlobalAnnouncement($"{winningControllerDisplay} has captured {area.Name} and is victorious!", "Round", false, null, Color.Green);
-                        _roundEndSystem.EndRound();
-                        return; // Round ended, no further processing for this area needed.
+                        if (canWinByCapture && !string.IsNullOrEmpty(winningControllerDisplay))
+                        {
+                            _chat.DispatchGlobalAnnouncement($"{winningControllerDisplay} has captured {area.Name} and is victorious!", "Round", false, null, Color.Green);
+                            _roundEndSystem.EndRound();
+                            return; // Round ended, no further processing for this area needed.
+                        }
                     }
                 }
             }

+ 17 - 0
Content.Server/GameTicking/Rules/Components/CaptureAreaComponent.cs

@@ -28,6 +28,23 @@ public sealed partial class CaptureAreaRuleComponent : Component
     /// </summary>
     [DataField("asymmetricGameTimeElapsed"), ViewVariables(VVAccess.ReadWrite)]
     public float AsymmetricGameTimeElapsed { get; set; } = 0f;
+
+    //for points-based
+    /// <summary>
+    /// The first faction that can get points from capture.
+    /// </summary>
+    [DataField("pointsFactionName1")]
+    public string PointsFactionName1 { get; set; } = "";
+    /// <summary>
+    /// The first faction that can get points from capture.
+    /// </summary>
+    [DataField("pointsFactionName2")]
+    public string PointsFactionName2 { get; set; } = "";
+    /// <summary>
+    /// How many points per minute
+    /// </summary>
+    [DataField("pointsPerMinute")]
+    public int PointsPerMinute { get; set; } = 0;
 }
 [RegisterComponent]
 public sealed partial class CaptureAreaComponent : Component

+ 20 - 0
Content.Server/GameTicking/Rules/Components/ValleyCheckpointComponent.cs

@@ -0,0 +1,20 @@
+namespace Content.Server.GameTicking.Rules.Components;
+
+/// <summary>
+/// Marks an entity as a Valley checkpoint for supply box deliveries and control points.
+/// </summary>
+[RegisterComponent, Access(typeof(ValleyPointsRuleSystem))]
+public sealed partial class ValleyCheckpointComponent : Component
+{
+    /// <summary>
+    /// Whether this checkpoint is controlled by Blugoslavia.
+    /// </summary>
+    [DataField]
+    public bool BlugoslaviaControlled = false;
+
+    /// <summary>
+    /// Supply boxes currently being secured at this checkpoint.
+    /// </summary>
+    [DataField]
+    public List<EntityUid> SecuringBoxes = new();
+}

+ 164 - 0
Content.Server/GameTicking/Rules/Components/ValleyPointsComponent.cs

@@ -0,0 +1,164 @@
+using Content.Shared.Roles;
+using Robust.Shared.Audio;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
+
+namespace Content.Server.GameTicking.Rules.Components;
+
+[RegisterComponent, Access(typeof(ValleyPointsRuleSystem))]
+public sealed partial class ValleyPointsComponent : Component
+{
+    /// <summary>
+    /// The current points for Blugoslavia.
+    /// </summary>
+    [DataField]
+    public int BlugoslaviaPoints = 0;
+
+    /// <summary>
+    /// The current points for the Insurgents.
+    /// </summary>
+    [DataField]
+    public int InsurgentPoints = 0;
+
+    /// <summary>
+    /// Points needed to win the match.
+    /// </summary>
+    [DataField]
+    public int PointsToWin = 1000;
+
+    /// <summary>
+    /// Match duration in minutes.
+    /// </summary>
+    [DataField]
+    public float MatchDurationMinutes = 50f;
+
+    /// <summary>
+    /// Points awarded for killing a Blugoslavian soldier.
+    /// </summary>
+    [DataField]
+    public int KillPoints = 30;
+
+    /// <summary>
+    /// Points awarded for delivering a supply box.
+    /// </summary>
+    [DataField]
+    public int SupplyBoxDeliveryPoints = 50;
+
+    /// <summary>
+    /// Points awarded for stealing a supply box.
+    /// </summary>
+    [DataField]
+    public int StolenSupplyBoxPoints = 75;
+
+    /// <summary>
+    /// Points awarded for escorting a convoy.
+    /// </summary>
+    [DataField]
+    public int ConvoyEscortPoints = 100;
+
+    /// <summary>
+    /// Points awarded for holding a checkpoint.
+    /// </summary>
+    [DataField]
+    public int CheckpointHoldPoints = 5;
+
+    /// <summary>
+    /// Bonus points for holding all checkpoints.
+    /// </summary>
+    [DataField]
+    public int AllCheckpointsBonusPoints = 100;
+
+    /// <summary>
+    /// Time in seconds to hold a checkpoint before earning points.
+    /// </summary>
+    [DataField]
+    public float CheckpointHoldTime = 60f; // 1 minute
+
+    /// <summary>
+    /// Time in seconds to secure a supply box at a checkpoint.
+    /// </summary>
+    [DataField]
+    public float SupplyBoxSecureTime = 30f;
+
+    /// <summary>
+    /// Interval in seconds for all-checkpoints bonus.
+    /// </summary>
+    [DataField]
+    public float CheckpointBonusInterval = 300f; // 5 minutes
+
+    /// <summary>
+    /// Initial count of civilian NPCs.
+    /// </summary>
+    [DataField]
+    public int InitialCivilianCount = 0;
+
+    /// <summary>
+    /// Total civilian NPCs.
+    /// </summary>
+    [DataField]
+    public int TotalCivilianNPCs = 0;
+    /// <summary>
+    /// Total civilian NPCs currently alive.
+    /// </summary>
+    [DataField]
+    public int AliveCivilianNPCs = 0;
+    /// <summary>
+    /// Required civilian survival rate for UN objectives (0.0 to 1.0).
+    /// </summary>
+    [DataField]
+    public float RequiredCivilianSurvivalRate = 0.8f; // 80%
+
+    /// <summary>
+    /// Whether the UN hospital zone is controlled by UN forces.
+    /// </summary>
+    [DataField]
+    public bool UNHospitalZoneControlled = true;
+
+    /// <summary>
+    /// Whether the UN has maintained neutrality.
+    /// </summary>
+    [DataField]
+    public bool UNNeutralityMaintained = true;
+
+    /// <summary>
+    /// When the game started.
+    /// </summary>
+    [DataField]
+    public TimeSpan GameStartTime;
+
+    /// <summary>
+    /// Last time the all-checkpoints bonus was awarded.
+    /// </summary>
+    [DataField]
+    public TimeSpan LastCheckpointBonusTime;
+
+    /// <summary>
+    /// Whether the game has ended.
+    /// </summary>
+    [DataField]
+    public bool GameEnded = false;
+
+    /// <summary>
+    /// Checkpoints currently held by Blugoslavia.
+    /// </summary>
+    [DataField]
+    public List<EntityUid> BlugoslaviaHeldCheckpoints = new();
+
+    /// <summary>
+    /// When each checkpoint started being held.
+    /// </summary>
+    [DataField]
+    public Dictionary<EntityUid, TimeSpan> CheckpointHoldStartTimes = new();
+
+    /// <summary>
+    /// Supply boxes currently being secured.
+    /// </summary>
+    [DataField]
+    public Dictionary<EntityUid, TimeSpan> SecuringSupplyBoxes = new();
+
+    /// <summary>
+    /// Last time scores were announced.
+    /// </summary>
+    [DataField]
+    public TimeSpan LastScoreAnnouncementTime;
+}

+ 20 - 0
Content.Server/GameTicking/Rules/Components/ValleySupplyBoxComponent.cs

@@ -0,0 +1,20 @@
+namespace Content.Server.GameTicking.Rules.Components;
+
+/// <summary>
+/// Marks an entity as a Valley supply box that can be delivered for points.
+/// </summary>
+[RegisterComponent, Access(typeof(ValleyPointsRuleSystem))]
+public sealed partial class ValleySupplyBoxComponent : Component
+{
+    /// <summary>
+    /// Whether this supply box has been delivered to a checkpoint.
+    /// </summary>
+    [DataField]
+    public bool Delivered = false;
+
+    /// <summary>
+    /// The checkpoint this box is being secured at, if any.
+    /// </summary>
+    [DataField]
+    public EntityUid? SecuringAtCheckpoint = null;
+}

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

@@ -82,6 +82,10 @@ private void OnSpawnComplete(PlayerSpawnCompleteEvent ev)
             {
                 if (TryComp<NpcFactionMemberComponent>(ev.Mob, out var npc))
                 {
+                    if (npc.Factions.First() == "UnitedNations")
+                    {
+                        return;
+                    }
                     if (npc.Factions.Count > 0 && npc.Factions.First() != component.Team2)
                     {
                         component.Team1 = npc.Factions.First();
@@ -92,6 +96,10 @@ private void OnSpawnComplete(PlayerSpawnCompleteEvent ev)
             {
                 if (TryComp<NpcFactionMemberComponent>(ev.Mob, out var npc))
                 {
+                    if (npc.Factions.First() == "UnitedNations")
+                    {
+                        return;
+                    }
                     if (npc.Factions.Count > 0 && npc.Factions.First() != component.Team1)
                     {
                         component.Team2 = npc.Factions.First();

+ 575 - 0
Content.Server/GameTicking/Rules/ValleyPointsSystem.cs

@@ -0,0 +1,575 @@
+using System.Linq;
+using Content.Server.GameTicking.Rules.Components;
+using Content.Server.Chat.Managers;
+using Content.Server.Popups;
+using Content.Shared.GameTicking.Components;
+using Content.Shared.Mobs;
+using Content.Shared.Mobs.Components;
+using Content.Shared.NPC.Components;
+using Content.Shared.Interaction;
+using Content.Shared.Hands.EntitySystems;
+using Robust.Shared.Timing;
+using Content.Server.KillTracking;
+using Content.Shared.NPC.Systems;
+
+
+namespace Content.Server.GameTicking.Rules;
+
+/// <summary>
+/// Handles the Valley gamemode points system for Blugoslavia vs Insurgents
+/// </summary>
+public sealed class ValleyPointsRuleSystem : GameRuleSystem<ValleyPointsComponent>
+{
+    [Dependency] private readonly ILogManager _logManager = default!;
+    [Dependency] private readonly IGameTiming _timing = default!;
+    [Dependency] private readonly IChatManager _chatManager = default!;
+    [Dependency] private readonly PopupSystem _popup = default!;
+    [Dependency] private readonly EntityLookupSystem _lookup = default!;
+    [Dependency] private readonly SharedTransformSystem _transform = default!;
+    [Dependency] private readonly SharedHandsSystem _hands = default!;
+
+    [Dependency] private readonly NpcFactionSystem _factionSystem = default!; // Added dependency
+    private ISawmill _sawmill = default!;
+    private TimeSpan _lastSupplyBoxCheck = TimeSpan.Zero;
+    private const float SupplyBoxCheckInterval = 30f; // Check every 30 seconds
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        _sawmill = _logManager.GetSawmill("valley-points");
+
+        SubscribeLocalEvent<MobStateChangedEvent>(OnMobStateChanged);
+        SubscribeLocalEvent<CaptureAreaComponent, ComponentStartup>(OnCaptureAreaStartup);
+        SubscribeLocalEvent<KillReportedEvent>(OnKillReported);
+    }
+
+    protected override void Started(EntityUid uid, ValleyPointsComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
+    {
+        component.GameStartTime = _timing.CurTime;
+        component.LastCheckpointBonusTime = _timing.CurTime;
+        component.LastScoreAnnouncementTime = _timing.CurTime;
+        _lastSupplyBoxCheck = _timing.CurTime;
+
+        // Initialize checkpoints immediately
+        InitializeCheckpoints(component);
+
+        // Delay civilian count initialization to allow spawning
+        Timer.Spawn(TimeSpan.FromSeconds(5), () => InitializeCivilianCount(component));
+
+        _sawmill.Info("Valley gamemode started - 50 minute timer begins now");
+        AnnounceToAll("Valley conflict has begun! Blugoslavia and Insurgents fight for control.");
+    }
+
+    private void OnCaptureAreaStartup(EntityUid uid, CaptureAreaComponent component, ComponentStartup args)
+    {
+        if (HasComp<ValleyCheckpointComponent>(uid))
+        {
+            component.CapturableFactions.Clear();
+            component.CapturableFactions.Add("Blugoslavia");
+            component.CapturableFactions.Add("Insurgents");
+        }
+    }
+
+    private void OnMobStateChanged(MobStateChangedEvent args)
+    {
+        if (args.NewMobState == MobState.Dead && args.OldMobState == MobState.Alive)
+        {
+            if (TryComp<NpcFactionMemberComponent>(args.Target, out var factionMember) &&
+                factionMember.Factions.Any(f => f == "Blugoslavia"))
+            {
+                var ruleQuery = EntityQueryEnumerator<ValleyPointsComponent>();
+                if (ruleQuery.MoveNext(out var ruleEntity, out _))
+                {
+                    AwardInsurgentKill(ruleEntity);
+                }
+            }
+        }
+    }
+
+    private void InitializeCivilianCount(ValleyPointsComponent component)
+    {
+        // Count civilian NPCs on the map
+        var civilianCount = 0;
+        var query = EntityQueryEnumerator<NpcFactionMemberComponent>();
+        while (query.MoveNext(out _, out var faction))
+        {
+            if (faction.Factions.Any(f => f == "Civilian"))
+                civilianCount++;
+        }
+
+        component.InitialCivilianCount = civilianCount;
+        component.TotalCivilianNPCs = civilianCount;
+        _sawmill.Info($"Initialized with {civilianCount} civilian NPCs");
+    }
+
+    private void InitializeCheckpoints(ValleyPointsComponent valley)
+    {
+        var checkpointQuery = EntityQueryEnumerator<ValleyCheckpointComponent, CaptureAreaComponent>();
+        while (checkpointQuery.MoveNext(out var uid, out var checkpoint, out var area))
+        {
+            area.CapturableFactions.Clear();
+            area.CapturableFactions.Add("Blugoslavia");
+            area.CapturableFactions.Add("Insurgents");
+
+            _sawmill.Info($"Initialized Valley checkpoint: {area.Name}");
+        }
+    }
+
+    public override void Update(float frameTime)
+    {
+        base.Update(frameTime);
+
+        var query = EntityQueryEnumerator<ValleyPointsComponent, GameRuleComponent>();
+        while (query.MoveNext(out var uid, out var valley, out var gameRule))
+        {
+            if (!GameTicker.IsGameRuleAdded(uid, gameRule))
+                continue;
+
+            if (valley.GameEnded)
+                continue;
+
+            UpdateCheckpointHolding(valley);
+            UpdateSupplyBoxSecuring(valley);
+            CheckCaptureAreaControl(valley);
+            CheckSupplyBoxDeliveries(valley);
+            CheckScoreAnnouncement(valley);
+            CheckWinConditions(uid, valley);
+            CheckTimeLimit(uid, valley);
+        }
+    }
+
+    private void CheckSupplyBoxDeliveries(ValleyPointsComponent valley)
+    {
+        var currentTime = _timing.CurTime;
+
+        // Only check every 30 seconds
+        if ((currentTime - _lastSupplyBoxCheck).TotalSeconds < SupplyBoxCheckInterval)
+            return;
+
+        _lastSupplyBoxCheck = currentTime;
+
+        // Check all capture areas for nearby supply boxes
+        var areaQuery = EntityQueryEnumerator<CaptureAreaComponent>();
+        while (areaQuery.MoveNext(out var areaUid, out var area))
+        {
+            var areaPos = _transform.GetMapCoordinates(areaUid);
+            var nearbyEntities = _lookup.GetEntitiesInRange(areaPos, 3f);
+
+            foreach (var entity in nearbyEntities)
+            {
+                if (TryComp<ValleySupplyBoxComponent>(entity, out var supplyBox) && !supplyBox.Delivered)
+                {
+                    // Check if this is a checkpoint controlled by Blugoslavia
+                    if (HasComp<ValleyCheckpointComponent>(areaUid) && area.Controller == "Blugoslavia")
+                    {
+                        ProcessBlugoslavianSupplyDelivery(valley, entity, areaUid, area);
+                    }
+                    // Check if this is the Insurgent base
+                    else if (IsInsurgentBase(areaUid, area))
+                    {
+                        ProcessInsurgentSupplyTheft(valley, entity, areaUid, area);
+                    }
+                }
+            }
+        }
+    }
+
+    private bool IsInsurgentBase(EntityUid areaUid, CaptureAreaComponent area)
+    {
+        // Check if this area is marked as insurgent base
+        return area.Name.ToLower().Contains("insurgent");
+
+    }
+
+    private void ProcessBlugoslavianSupplyDelivery(ValleyPointsComponent valley, EntityUid supplyBox, EntityUid checkpoint, CaptureAreaComponent area)
+    {
+        if (!TryComp<ValleySupplyBoxComponent>(supplyBox, out var boxComp))
+            return;
+
+        boxComp.Delivered = true;
+        boxComp.SecuringAtCheckpoint = checkpoint;
+
+        // Start securing timer
+        valley.SecuringSupplyBoxes[supplyBox] = _timing.CurTime;
+
+        _sawmill.Info($"Supply box delivery started at {area.Name}, securing for {valley.SupplyBoxSecureTime} seconds");
+        AnnounceToAll($"Blugoslavia supply box delivery started at {area.Name}!");
+    }
+
+    private void ProcessInsurgentSupplyTheft(ValleyPointsComponent valley, EntityUid supplyBox, EntityUid baseArea, CaptureAreaComponent area)
+    {
+        if (!TryComp<ValleySupplyBoxComponent>(supplyBox, out var boxComp))
+            return;
+
+        boxComp.Delivered = true;
+
+        // Award points immediately for insurgent theft
+        valley.InsurgentPoints += valley.StolenSupplyBoxPoints;
+        _sawmill.Info($"Insurgents awarded {valley.StolenSupplyBoxPoints} points for stolen supply box at {area.Name}. Total: {valley.InsurgentPoints}");
+        AnnounceToAll($"Insurgents: +{valley.StolenSupplyBoxPoints} points (Supply Theft at {area.Name}) - Total: {valley.InsurgentPoints}");
+
+        // Remove the supply box
+        QueueDel(supplyBox);
+    }
+
+    private void CheckCaptureAreaControl(ValleyPointsComponent valley)
+    {
+        var checkpointQuery = EntityQueryEnumerator<ValleyCheckpointComponent, CaptureAreaComponent>();
+        while (checkpointQuery.MoveNext(out var uid, out var checkpoint, out var area))
+        {
+            var blugoslaviaControlled = area.Controller == "Blugoslavia";
+
+            if (checkpoint.BlugoslaviaControlled != blugoslaviaControlled)
+            {
+                checkpoint.BlugoslaviaControlled = blugoslaviaControlled;
+                SetCheckpointControl(valley, uid, blugoslaviaControlled);
+            }
+        }
+    }
+
+    public void SetCheckpointControl(ValleyPointsComponent valley, EntityUid checkpoint, bool blugoslaviaControlled)
+    {
+        if (blugoslaviaControlled)
+        {
+            if (!valley.BlugoslaviaHeldCheckpoints.Contains(checkpoint))
+            {
+                valley.BlugoslaviaHeldCheckpoints.Add(checkpoint);
+                valley.CheckpointHoldStartTimes[checkpoint] = _timing.CurTime;
+                _sawmill.Info($"Blugoslavia gained control of checkpoint {checkpoint}");
+            }
+        }
+        else
+        {
+            if (valley.BlugoslaviaHeldCheckpoints.Contains(checkpoint))
+            {
+                valley.BlugoslaviaHeldCheckpoints.Remove(checkpoint);
+                valley.CheckpointHoldStartTimes.Remove(checkpoint);
+                _sawmill.Info($"Blugoslavia lost control of checkpoint {checkpoint}");
+            }
+        }
+    }
+
+    private void UpdateCheckpointHolding(ValleyPointsComponent valley)
+    {
+        var currentTime = _timing.CurTime;
+        var checkpointsToAward = new List<EntityUid>();
+
+        // Check individual checkpoint holding - award points every minute (60 seconds)
+        foreach (var kvp in valley.CheckpointHoldStartTimes.ToList())
+        {
+            var checkpoint = kvp.Key;
+            var startTime = kvp.Value;
+
+            if ((currentTime - startTime).TotalSeconds >= 60f) // 1 minute instead of 5
+            {
+                checkpointsToAward.Add(checkpoint);
+                valley.CheckpointHoldStartTimes[checkpoint] = currentTime;
+            }
+        }
+
+        if (checkpointsToAward.Count > 0)
+        {
+            var pointsAwarded = checkpointsToAward.Count * 5; // 5 points per minute instead of 25 per 5 minutes
+            valley.BlugoslaviaPoints += pointsAwarded;
+            _sawmill.Info($"Blugoslavia awarded {pointsAwarded} points for holding {checkpointsToAward.Count} checkpoints");
+            AnnounceToAll($"Blugoslavia: +{pointsAwarded} points (Checkpoint Control) - Total: {valley.BlugoslaviaPoints}");
+        }
+
+        // Check for all checkpoints bonus - still every 5 minutes but reduced frequency
+        if (valley.BlugoslaviaHeldCheckpoints.Count >= 4 && // Assuming 4 checkpoints total
+            (currentTime - valley.LastCheckpointBonusTime).TotalSeconds >= valley.CheckpointBonusInterval)
+        {
+            valley.BlugoslaviaPoints += valley.AllCheckpointsBonusPoints;
+            valley.LastCheckpointBonusTime = currentTime;
+            _sawmill.Info($"Blugoslavia awarded {valley.AllCheckpointsBonusPoints} bonus points for controlling all checkpoints");
+            AnnounceToAll($"Blugoslavia: +{valley.AllCheckpointsBonusPoints} points (All Checkpoints Bonus) - Total: {valley.BlugoslaviaPoints}");
+        }
+    }
+
+    private void UpdateSupplyBoxSecuring(ValleyPointsComponent valley)
+    {
+        var currentTime = _timing.CurTime;
+        var securedBoxes = new List<EntityUid>();
+
+        // Check all checkpoints for securing boxes
+        var checkpointQuery = EntityQueryEnumerator<ValleyCheckpointComponent>();
+        while (checkpointQuery.MoveNext(out var checkpointUid, out var checkpoint))
+        {
+            var boxesToRemove = new List<EntityUid>();
+
+            foreach (var boxUid in checkpoint.SecuringBoxes)
+            {
+                if (!TryComp<ValleySupplyBoxComponent>(boxUid, out var boxComp))
+                {
+                    boxesToRemove.Add(boxUid);
+                    continue;
+                }
+
+                // Check if box is still near the checkpoint
+                var boxPos = _transform.GetMapCoordinates(boxUid);
+                var checkpointPos = _transform.GetMapCoordinates(checkpointUid);
+
+                if ((boxPos.Position - checkpointPos.Position).Length() > 3f)
+                {
+                    // Box moved away, cancel securing
+                    boxesToRemove.Add(boxUid);
+                    boxComp.Delivered = false;
+                    boxComp.SecuringAtCheckpoint = null;
+                    _sawmill.Info("Supply box moved away from checkpoint, delivery cancelled");
+                    continue;
+                }
+
+                // Check if securing time has elapsed
+                if (valley.SecuringSupplyBoxes.TryGetValue(boxUid, out var startTime) &&
+                    (currentTime - startTime).TotalSeconds >= valley.SupplyBoxSecureTime)
+                {
+                    securedBoxes.Add(boxUid);
+                    boxesToRemove.Add(boxUid);
+                }
+            }
+
+            // Remove boxes that are no longer securing
+            foreach (var box in boxesToRemove)
+            {
+                checkpoint.SecuringBoxes.Remove(box);
+            }
+        }
+
+        // Award points for secured boxes
+        foreach (var box in securedBoxes)
+        {
+            valley.SecuringSupplyBoxes.Remove(box);
+            valley.BlugoslaviaPoints += valley.SupplyBoxDeliveryPoints;
+            _sawmill.Info($"Blugoslavia awarded {valley.SupplyBoxDeliveryPoints} points for secured supply box delivery");
+            AnnounceToAll($"Blugoslavia: +{valley.SupplyBoxDeliveryPoints} points (Supply Delivery) - Total: {valley.BlugoslaviaPoints}");
+
+            // Delete the secured box
+            QueueDel(box);
+        }
+    }
+
+    /// <summary>
+    /// Award points to Blugoslavia for delivering a supply box to a checkpoint.
+    /// </summary>
+    public void AwardSupplyBoxDelivery(EntityUid ruleEntity, EntityUid checkpoint, EntityUid supplyBox)
+    {
+        if (!TryComp<ValleyPointsComponent>(ruleEntity, out var valley))
+            return;
+
+        // Start securing timer
+        valley.SecuringSupplyBoxes[supplyBox] = _timing.CurTime;
+        _sawmill.Info($"Supply box delivery started at checkpoint, securing for {valley.SupplyBoxSecureTime} seconds");
+    }
+
+    /// <summary>
+    /// Award points to insurgents for killing a Blugoslavian soldier.
+    /// </summary>
+    public void AwardInsurgentKill(EntityUid ruleEntity)
+    {
+        if (!TryComp<ValleyPointsComponent>(ruleEntity, out var valley))
+            return;
+
+        valley.InsurgentPoints += valley.KillPoints;
+        _sawmill.Info($"Insurgents awarded {valley.KillPoints} points for kill. Total: {valley.InsurgentPoints}");
+        AnnounceToAll($"Insurgents: +{valley.KillPoints} points (Kill) - Total: {valley.InsurgentPoints}");
+    }
+
+    /// <summary>
+    /// Award points to insurgents for stealing and delivering a supply box.
+    /// </summary>
+    public void AwardStolenSupplyBox(EntityUid ruleEntity)
+    {
+        if (!TryComp<ValleyPointsComponent>(ruleEntity, out var valley))
+            return;
+
+        valley.InsurgentPoints += valley.StolenSupplyBoxPoints;
+        _sawmill.Info($"Insurgents awarded {valley.StolenSupplyBoxPoints} points for stolen supply box. Total: {valley.InsurgentPoints}");
+        AnnounceToAll($"Insurgents: +{valley.StolenSupplyBoxPoints} points (Supply Theft) - Total: {valley.InsurgentPoints}");
+    }
+
+    /// <summary>
+    /// Award points to Blugoslavia for successfully escorting a convoy.
+    /// </summary>
+    public void AwardConvoyEscort(EntityUid ruleEntity)
+    {
+        if (!TryComp<ValleyPointsComponent>(ruleEntity, out var valley))
+            return;
+
+        valley.BlugoslaviaPoints += valley.ConvoyEscortPoints;
+        _sawmill.Info($"Blugoslavia awarded {valley.ConvoyEscortPoints} points for convoy escort. Total: {valley.BlugoslaviaPoints}");
+        AnnounceToAll($"Blugoslavia: +{valley.ConvoyEscortPoints} points (Convoy Escort) - Total: {valley.BlugoslaviaPoints}");
+    }
+
+    private void CheckWinConditions(EntityUid uid, ValleyPointsComponent valley)
+    {
+        if (valley.BlugoslaviaPoints >= valley.PointsToWin)
+        {
+            EndGame(uid, valley, "Blugoslavia");
+        }
+        else if (valley.InsurgentPoints >= valley.PointsToWin)
+        {
+            EndGame(uid, valley, "Insurgents");
+        }
+    }
+
+    private void CheckTimeLimit(EntityUid uid, ValleyPointsComponent valley)
+    {
+        var elapsed = (_timing.CurTime - valley.GameStartTime).TotalMinutes;
+        if (elapsed >= valley.MatchDurationMinutes)
+        {
+            // Determine winner by points
+            if (valley.BlugoslaviaPoints > valley.InsurgentPoints)
+            {
+                EndGame(uid, valley, "Blugoslavia");
+            }
+            else if (valley.InsurgentPoints > valley.BlugoslaviaPoints)
+            {
+                EndGame(uid, valley, "Insurgents");
+            }
+            else
+            {
+                EndGame(uid, valley, "Draw");
+            }
+        }
+    }
+
+    private void EndGame(EntityUid uid, ValleyPointsComponent valley, string winner)
+    {
+        valley.GameEnded = true;
+
+        var finalMessage = winner switch
+        {
+            "Blugoslavia" => $"VICTORY: Blugoslavia wins with {valley.BlugoslaviaPoints} points!",
+            "Insurgents" => $"VICTORY: Insurgents win with {valley.InsurgentPoints} points!",
+            "Draw" => $"DRAW: Match ended in a tie! Blugoslavia: {valley.BlugoslaviaPoints}, Insurgents: {valley.InsurgentPoints}",
+            _ => "Match ended."
+        };
+
+        _sawmill.Info($"Valley gamemode ended: {finalMessage}");
+        AnnounceToAll(finalMessage);
+
+        // Check UN objectives
+        AnnounceToAll(CheckUNObjectives(valley));
+    }
+    private string CheckUNObjectives(ValleyPointsComponent valley)
+    {
+        var civilianSurvivalRate = valley.TotalCivilianNPCs > 0
+            ? (float)valley.AliveCivilianNPCs / valley.TotalCivilianNPCs
+            : 1.0f;
+
+        var query = EntityQueryEnumerator<CaptureAreaComponent>();
+        while (query.MoveNext(out var uid, out var area))
+        {
+            if (area.Name == "UN Hospital")
+            {
+                if (area.Occupied == true)
+                {
+                    valley.UNHospitalZoneControlled = false;
+                }
+                else
+                {
+                    valley.UNHospitalZoneControlled = true;
+                }
+            }
+        }
+
+        var unSuccess = civilianSurvivalRate >= valley.RequiredCivilianSurvivalRate &&
+                       valley.UNHospitalZoneControlled &&
+                       valley.UNNeutralityMaintained;
+
+        var unMessage = unSuccess
+            ? $"UN OBJECTIVES COMPLETED: {civilianSurvivalRate:P0} civilian survival rate maintained, hospital zone secured, neutrality preserved."
+            : $"UN OBJECTIVES FAILED: {civilianSurvivalRate:P0} civilian survival rate, hospital zone: {(valley.UNHospitalZoneControlled ? "Secured" : "Lost")}, neutrality: {(valley.UNNeutralityMaintained ? "Maintained" : "Violated")}";
+
+        _sawmill.Info(unMessage);
+        return unMessage;
+    }
+
+    private void AnnounceToAll(string message)
+    {
+        _chatManager.DispatchServerAnnouncement(message);
+    }
+
+    protected override void AppendRoundEndText(EntityUid uid, ValleyPointsComponent component, GameRuleComponent gameRule, ref RoundEndTextAppendEvent args)
+    {
+
+        if (component.BlugoslaviaPoints > component.InsurgentPoints)
+        {
+            args.AddLine($"[color=lime]Blugoslavia[/color] has won!");
+        }
+        else if (component.BlugoslaviaPoints < component.InsurgentPoints)
+        {
+            args.AddLine($"[color=lime]Insurgents[/color] have won!");
+
+        }
+        else
+        {
+            args.AddLine("The round ended in a [color=yellow]draw[/color]!");
+        }
+        args.AddLine("");
+        args.AddLine($"Blugoslavia: {component.BlugoslaviaPoints} points");
+        args.AddLine($"Insurgents: {component.InsurgentPoints} points");
+        args.AddLine("");
+        args.AddLine($"UN Objectives:");
+        args.AddLine(CheckUNObjectives(component));
+    }
+    private void OnKillReported(ref KillReportedEvent ev)
+    {
+        var query = EntityQueryEnumerator<ValleyPointsComponent, GameRuleComponent>();
+        while (query.MoveNext(out var uid, out var valley, out var rule))
+        {
+            if (!GameTicker.IsGameRuleActive(uid, rule))
+                continue;
+
+            // Check if UN member was involved (either as killer or victim) TODO: Check killer
+            bool unInvolved = false;
+
+            // Check if victim is UN
+            if (TryComp<NpcFactionMemberComponent>(ev.Entity, out var victimFaction))
+            {
+                if (_factionSystem.IsMember(ev.Entity, "UnitedNations"))
+                {
+                    unInvolved = true;
+                }
+
+                // If UN was involved, set neutrality to false
+                if (unInvolved && valley.UNNeutralityMaintained)
+                {
+                    valley.UNNeutralityMaintained = false;
+                    _sawmill.Info("UN neutrality violated - UN member involved in combat");
+                    AnnounceToAll("UN neutrality has been violated!");
+                }
+
+                // Award points to Insurgents for killing Blugoslavian soldiers
+                if (TryComp<NpcFactionMemberComponent>(ev.Entity, out var deadFaction) &&
+                    deadFaction.Factions.Any(f => f == "Blugoslavia"))
+                {
+                    valley.InsurgentPoints += valley.KillPoints;
+                    _sawmill.Info($"Insurgents awarded {valley.KillPoints} points for Blugoslavian kill. Total: {valley.InsurgentPoints}");
+                    AnnounceToAll($"Insurgents: +{valley.KillPoints} points (Kill) - Total: {valley.InsurgentPoints}");
+                }
+            }
+        }
+    }
+
+    private void CheckScoreAnnouncement(ValleyPointsComponent valley)
+    {
+        var currentTime = _timing.CurTime;
+
+        // Announce scores every 5 minutes (300 seconds)
+        if ((currentTime - valley.LastScoreAnnouncementTime).TotalSeconds >= 300f)
+        {
+            valley.LastScoreAnnouncementTime = currentTime;
+
+            var elapsedMinutes = (currentTime - valley.GameStartTime).TotalMinutes;
+            var remainingMinutes = valley.MatchDurationMinutes - elapsedMinutes;
+
+            var scoreMessage = $"SCORE UPDATE ({remainingMinutes:F0} minutes remaining): " +
+                              $"Blugoslavia: {valley.BlugoslaviaPoints} points | " +
+                              $"Insurgents: {valley.InsurgentPoints} points";
+
+            _sawmill.Info($"Score announcement: {scoreMessage}");
+            AnnounceToAll(scoreMessage);
+        }
+    }
+}

+ 14 - 0
Content.Server/_Stalker/Teleports/LocalTeleport/LocalTeleportComponent.cs

@@ -0,0 +1,14 @@
+namespace Content.Server._Stalker.Teleports.LocalTeleport;
+/// <summary>
+/// Contains portal name for <see cref="LocalTeleportSystem"/>
+/// </summary>
+[RegisterComponent]
+public sealed partial class LocalTeleportComponent : Component
+{
+    // Portal name to link two portals with the same name together
+    [DataField("portalName"), ViewVariables(VVAccess.ReadWrite)]
+    public string? PortalName = string.Empty;
+
+    [DataField]
+    public bool AllowAll;
+}

+ 94 - 0
Content.Server/_Stalker/Teleports/LocalTeleport/LocalTeleportSystem.cs

@@ -0,0 +1,94 @@
+using System.Linq;
+using Content.Shared._Stalker.Teleport;
+using Content.Shared.Access.Systems;
+using Content.Shared.Movement.Pulling.Systems;
+using Content.Shared.Teleportation.Components;
+using Content.Shared.Teleportation.Systems;
+using Robust.Shared.Physics.Events;
+using Robust.Shared.Random;
+
+namespace Content.Server._Stalker.Teleports.LocalTeleport;
+/// <summary>
+/// Use to teleport entities between maps/grids/tiles. Just spawn two portals with the same name.
+/// </summary>
+public sealed class LocalTeleportSystem : SharedTeleportSystem
+{
+    [Dependency] private readonly PullingSystem _pulling = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly SharedTransformSystem _xformSystem = default!;
+    [Dependency] private readonly LinkedEntitySystem _linkedEntitySystem = default!;
+    [Dependency] private readonly IEntityManager _entMan = default!;
+    [Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
+
+    public override void Initialize()
+    {
+        SubscribeLocalEvent<LocalTeleportComponent, StartCollideEvent>(OnStartCollide);
+        SubscribeLocalEvent<LocalTeleportComponent, EndCollideEvent>(OnEndCollide);
+    }
+
+    private void OnStartCollide(EntityUid uid, LocalTeleportComponent component, ref StartCollideEvent args)
+    {
+        var subject = args.OtherEntity;
+
+        // Check for access
+        if (!component.AllowAll)
+        {
+            if (!_accessReaderSystem.IsAllowed(args.OtherEntity, args.OurEntity))
+                return;
+        }
+
+        // Asked to remove, testing now
+        // if (TryComp<SharedPullableComponent>(subject, out var pullable) && pullable.BeingPulled)
+        //     _pulling.TryStopPull(pullable);
+        //
+        // if (TryComp<SharedPullerComponent>(subject, out var pulling)
+        //     && pulling.Pulling != null && TryComp<SharedPullableComponent>(pulling.Pulling.Value, out var subjectPulling))
+        //     _pulling.TryStopPull(subjectPulling);
+
+        // Remove Timeout from other portal
+        if (HasComp<PortalTimeoutComponent>(subject))
+            return;
+
+        // If there are no linked entity - link one
+        if (!TryComp<LinkedEntityComponent>(uid, out var link))
+        {
+            var ents = _entMan.GetEntities();
+            foreach (var ent in ents)
+            {
+                if (!TryComp<LocalTeleportComponent>(ent, out var local))
+                    continue;
+
+                if (local.PortalName != component.PortalName || uid == ent)
+                    continue;
+
+                _linkedEntitySystem.TryLink(uid, ent, true);
+            }
+        }
+        if (link == null)
+            return;
+
+        if (!link.LinkedEntities.Any())
+            return;
+
+        var target = _random.Pick(link.LinkedEntities);
+
+        // Setup Timeout for an entity to not teleport it after teleport...
+        var timeout = EnsureComp<PortalTimeoutComponent>(subject);
+        timeout.EnteredPortal = uid;
+        Dirty(subject, timeout);
+
+        var xform = Transform(target);
+        TeleportEntity(subject, xform.Coordinates);
+    }
+
+    private void OnEndCollide(EntityUid uid, LocalTeleportComponent component, ref EndCollideEvent args)
+    {
+        var subject = args.OtherEntity;
+
+        // Remove Timeout set by other portal.
+        if (TryComp<PortalTimeoutComponent>(subject, out var timeout) && timeout.EnteredPortal != uid)
+        {
+            RemCompDeferred<PortalTimeoutComponent>(subject);
+        }
+    }
+}

+ 18 - 5
Content.Shared/Access/Systems/AccessReaderSystem.cs

@@ -28,11 +28,13 @@ public sealed class AccessReaderSystem : EntitySystem
     [Dependency] private readonly SharedHandsSystem _handsSystem = default!;
     [Dependency] private readonly SharedContainerSystem _containerSystem = default!;
     [Dependency] private readonly SharedStationRecordsSystem _recordsSystem = default!;
-
+    [Dependency] private readonly ILogManager _log = default!;
+    public const string Sawmill = "accessreader";
+    protected ISawmill _sawmill = default!;
     public override void Initialize()
     {
         base.Initialize();
-
+        _sawmill = _log.GetSawmill(Sawmill);
         SubscribeLocalEvent<AccessReaderComponent, GotEmaggedEvent>(OnEmagged);
         SubscribeLocalEvent<AccessReaderComponent, LinkAttemptEvent>(OnLinkAttempt);
 
@@ -121,9 +123,20 @@ public bool IsAllowed(EntityUid user, EntityUid target, AccessReaderComponent? r
             return true;
         }
 
+        //Also check if the user has access levels in their components
+        if (TryComp<AccessComponent>(user, out var comp))
+        {
+            foreach (var tag in comp.Tags)
+            {
+                foreach (var alist in reader.AccessLists)
+                {
+                    if (alist.Contains(tag))
+                        return true;
+                }
+            }
+        }
         return false;
     }
-
     public bool GetMainAccessReader(EntityUid uid, [NotNullWhen(true)] out Entity<AccessReaderComponent>? ent)
     {
         ent = null;
@@ -273,7 +286,7 @@ public ICollection<ProtoId<AccessLevelPrototype>> FindAccessTags(EntityUid uid,
             FindAccessTagsItem(ent, ref tags, ref owned);
         }
 
-        return (ICollection<ProtoId<AccessLevelPrototype>>?) tags ?? Array.Empty<ProtoId<AccessLevelPrototype>>();
+        return (ICollection<ProtoId<AccessLevelPrototype>>?)tags ?? Array.Empty<ProtoId<AccessLevelPrototype>>();
     }
 
     /// <summary>
@@ -334,7 +347,7 @@ public void SetAccesses(EntityUid uid, AccessReaderComponent component, List<Pro
         component.AccessLists.Clear();
         foreach (var access in accesses)
         {
-            component.AccessLists.Add(new HashSet<ProtoId<AccessLevelPrototype>>(){access});
+            component.AccessLists.Add(new HashSet<ProtoId<AccessLevelPrototype>>() { access });
         }
         Dirty(uid, component);
         RaiseLocalEvent(uid, new AccessReaderConfigurationChangedEvent());

+ 17 - 0
Content.Shared/_Stalker/Teleport/DuplicateSymbolsPrototype.cs

@@ -0,0 +1,17 @@
+using Robust.Shared.Prototypes;
+
+namespace Content.Server._Stalker.Teleports.DuplicateTeleport;
+
+/// <summary>
+/// This is a prototype for...
+/// </summary>
+[Prototype("duplicateSymbols")]
+public sealed partial class DuplicateSymbolsPrototype : IPrototype
+{
+    /// <inheritdoc/>
+    [IdDataField]
+    public string ID { get; } = default!;
+
+    [DataField]
+    public List<string> Symbols = new();
+}

+ 14 - 0
Content.Shared/_Stalker/Teleport/MapLoaderPrototype.cs

@@ -0,0 +1,14 @@
+using Robust.Shared.Prototypes;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared._Stalker.Teleport;
+
+[Prototype("mapLoader"), Serializable, NetSerializable]
+public sealed class MapLoaderPrototype : IPrototype
+{
+    [IdDataField, ViewVariables]
+    public string ID { get; private set; } = default!;
+
+    [DataField]
+    public Dictionary<string, string> MapPaths = new();
+}

+ 33 - 0
Content.Shared/_Stalker/Teleport/SharedTeleportSystem.cs

@@ -0,0 +1,33 @@
+using System.Linq;
+using Robust.Shared.Map;
+
+namespace Content.Shared._Stalker.Teleport;
+
+public abstract class SharedTeleportSystem : EntitySystem
+{
+    [Dependency] private readonly SharedTransformSystem _xform = default!;
+    [Dependency] private readonly IMapManager _mapMan = default!;
+    protected void TeleportEntity(EntityUid entity, EntityCoordinates coords, bool reParent = true)
+    {
+        // raise before event so other systems can handle this
+        var originMapId = Transform(entity).MapID;
+        var destinationMapId = coords.GetMapId(EntityManager);
+        var beforeEvent = new BeforeEntityTeleportedEvent(entity, originMapId, destinationMapId);
+        RaiseLocalEvent(ref beforeEvent);
+
+        _xform.SetCoordinates(entity, coords);
+
+        var map = coords.GetMapUid(EntityManager);
+        if (map != null && reParent)
+            _xform.SetParent(entity, map.Value);
+
+        // raise after event for other systems to perform cleanup
+        var ev = new AfterEntityTeleportedEvent(entity, originMapId, destinationMapId);
+        RaiseLocalEvent(ref ev);
+    }
+}
+
+[ByRefEvent]
+public record struct AfterEntityTeleportedEvent(EntityUid EntityUid, MapId Origin, MapId Destination);
+[ByRefEvent]
+public record struct BeforeEntityTeleportedEvent(EntityUid EntityUid, MapId Origin, MapId Destination);

+ 2 - 2
Resources/ConfigPresets/Build/development.toml

@@ -2,11 +2,11 @@
 # Straight in-game baby
 lobbyenabled = true
 # Dev map for faster loading & convenience
-map = "Hotel"
+map = "Valley"
 role_timers = false
 lobbyduration = 15
 disallowlatejoins = false
-defaultpreset = "tdm-asymmetric"
+defaultpreset = "tdm"
 
 [events]
 enabled = false

+ 15 - 1
Resources/Locale/en-US/Civ14/jobs-descriptions.ftl

@@ -39,4 +39,18 @@ job-description-civ-sovietcw-cpt = You are the highest ranking in your faction.
 job-description-civ-sovietcw-sgt = You are the right hand of your captain. Direct troops and order artillery strikes on the enemy while answering to the Kapitan!
 job-description-civ-sovietcw-rifleman = You are a rifleman, the soviet standard of the army. For the Motherland!
 job-description-civ-sovietcw-machinegunner = You are a machinegunner. Use your superior firepower to suppress enemies at a distance!
-job-description-civ-sovietcw-medic = As a field surgeon, keep your troops alive!
+job-description-civ-sovietcw-medic = As a field surgeon, keep your troops alive!
+
+job-description-civ-insurgent-sgt = Direct your troops and order artillery strikes on the enemy!
+job-description-civ-insurgent-rifleman = You are an insurgent. Ambush your enemies and take them by surprise!
+job-description-civ-insurgent-machinegunner = You are a machinegunner. Use your superior firepower to suppress enemies at a distance!
+job-description-civ-insurgent-medic = As a field surgeon, keep your troops alive!
+
+job-description-civ-blugoslavia-cpt = You are the highest ranking in your faction. Lead your men to victory!
+job-description-civ-blugoslavia-sgt = You are the right hand of your captain. Direct troops and order artillery strikes on the enemy while answering to the Captain!
+job-description-civ-blugoslavia-rifleman = You are a rifleman, one of Blugoslavia's finest. Fight for victory!
+job-description-civ-blugoslavia-machinegunner = You are a machinegunner. Use your superior firepower to suppress enemies at a distance!
+job-description-civ-blugoslavia-medic = As a field surgeon, keep your troops alive!
+
+job-description-civ-unitednations-rifleman = You are a rifleman serving the UN in this area. Keep the peace and civilians safe!
+job-description-civ-unitednations-medic = As a field medic for the UN, keep civilians alive!

+ 16 - 1
Resources/Locale/en-US/Civ14/jobs.ftl

@@ -64,4 +64,19 @@ job-name-civ-sovietcw-sgt = Sergeant
 job-name-civ-sovietcw-submachinegunner = SMG
 job-name-civ-sovietcw-rifleman = Infantry
 job-name-civ-sovietcw-machinegunner = LMG
-job-name-civ-sovietcw-medic = Medic
+job-name-civ-sovietcw-medic = Medic
+
+job-name-civ-insurgent-sgt = Leader
+job-name-civ-insurgent-rifleman = Insurgent
+job-name-civ-insurgent-machinegunner = LMG
+job-name-civ-insurgent-medic = Medic
+
+job-name-civ-blugoslavia-cpt = Leader
+job-name-civ-blugoslavia-sgt = Sergeant
+job-name-civ-blugoslavia-submachinegunner = SMG
+job-name-civ-blugoslavia-rifleman = Infantry
+job-name-civ-blugoslavia-machinegunner = LMG
+job-name-civ-blugoslavia-medic = Medic
+
+job-name-civ-unitednations-rifleman = Infantry
+job-name-civ-unitednations-medic = Medic

+ 4 - 0
Resources/Locale/en-US/game-ticking/game-presets/preset-extended.ftl

@@ -7,3 +7,7 @@ tdm-description = Two factions competing to capture the target.
 
 tdm-asy-title = Team Deathmatch - Siege
 tdm-asy-description = One faction defends for a set period, another has to capture the target.
+
+tdm-valley-title = Points Gamemode - Valley
+tdm-valley-description = Factions need to gather 1000 points to win. Check gamebook/wiki for more info.
+

+ 5 - 1
Resources/Locale/en-US/guidebook/guides.ftl

@@ -100,6 +100,11 @@ guide-entry-yourfirstcharacter = Your First Character
 guide-entry-controls = Controls
 guide-entry-radio = Radio and Speech
 
+
+guide-entry-tdm = Team Deathmatch Gamemode
+guide-entry-valley = Valley Map
+guide-entry-mapping = Guide to Mapping
+
 guide-entry-references = Tables & References
 guide-entry-chemicals = Chemicals
 guide-entry-drinks = Drinks
@@ -202,4 +207,3 @@ guide-entry-rules-ban-types = Ban Types
 guide-entry-rules-ban-durations = Ban Durations
 
 guide-entry-writing = Writing
-guide-entry-glossary = Glossary

+ 5 - 0
Resources/Locale/en-US/headset/headset-component.ftl

@@ -23,3 +23,8 @@ chat-radio-binary = Binary
 
 chat-radio-soviet = Soviet
 chat-radio-us = US
+
+
+chat-radio-blugoslavia = Blugoslavia
+chat-radio-insurgents = Insurgents
+chat-radio-unitednations = United Nations

+ 6 - 3
Resources/Locale/en-US/job/department-desc.ftl

@@ -12,7 +12,10 @@ department-Specific-description = Jobs that not all stations have.
 department-Nomads-description = Nomads are not bound to any faction.
 department-French-description = The French are one of the factions present in this map.
 department-English-description = The English are one of the factions present in this map.
-department-German-description = The German are one of the factions present in this map.
-department-Soviet-description = The Soviet are one of the factions present in this map.
+department-German-description = The Germans are one of the factions present in this map.
+department-Soviet-description = The Soviets are one of the factions present in this map.
 department-US-description = The US are one of the factions present in this map.
-department-SovietCW-description = The Soviet Union are one of the factions present in this map.
+department-SovietCW-description = The Soviet Union are one of the factions present in this map.
+department-Insurgents-description = The Insurgents are one of the factions present in this map.
+department-Blugoslavia-description = Blugoslavia are one of the factions present in this map.
+department-UnitedNations-description = United Nations is one of the factions present in this map.

+ 3 - 0
Resources/Locale/en-US/job/department.ftl

@@ -16,3 +16,6 @@ department-German = Germany
 department-Soviet = Soviet Union
 department-US = United States
 department-SovietCW = Soviet Union
+department-Insurgents = Insurgents
+department-Blugoslavia = Blugoslavia
+department-UnitedNations = United Nations

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 79 - 0
Resources/Maps/civ/tdm/valley.yml


+ 14 - 10
Resources/Prototypes/Access/command.yml

@@ -13,16 +13,16 @@
 - type: accessGroup
   id: Command
   tags:
-  - Captain
-  - Command
-  - ChiefEngineer
-  - ChiefMedicalOfficer
-  - Cryogenics
-  - HeadOfPersonnel
-  - HeadOfSecurity
-  - Quartermaster
-  - ResearchDirector
-  
+    - Captain
+    - Command
+    - ChiefEngineer
+    - ChiefMedicalOfficer
+    - Cryogenics
+    - HeadOfPersonnel
+    - HeadOfSecurity
+    - Quartermaster
+    - ResearchDirector
+
 - type: accessLevel
   id: EmergencyShuttleRepealAll
   name: id-card-access-level-emergency-shuttle-repeal
@@ -31,3 +31,7 @@
 - type: accessLevel
   id: Cryogenics
   name: id-card-access-level-cryogenics
+
+- type: accessLevel
+  id: Insurgents
+  name: id-card-access-level-command

+ 8 - 3
Resources/Prototypes/Access/engineering.yml

@@ -13,6 +13,11 @@
 - type: accessGroup
   id: Engineering
   tags:
-  - ChiefEngineer
-  - Engineering
-  - Atmospherics
+    - ChiefEngineer
+    - Engineering
+    - Atmospherics
+
+- type: accessGroup
+  id: Insurgents
+  tags:
+    - Insurgents

+ 16 - 16
Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_accessories.yml

@@ -1061,6 +1061,17 @@
       cost: 5
       material: Cloth
       time: 5
+- type: entity
+  name: UN PASGT body armor
+  parent: civ13_accessory_woodland_PASGT_body_armor
+  id: civ13_accessory_un_PASGT_body_armor
+  description: Wearable armor that can stop most pistol rounds. This one is blue colored for use by the UN.
+  components:
+    - type: Sprite
+      sprite: Civ14/Clothing/exported/ties/pasgt_un.rsi
+    - type: Clothing
+      sprite: Civ14/Clothing/exported/ties/pasgt_un.rsi
+
 - type: entity
   name: red tie
   parent: ClothingNeckBase
@@ -3767,7 +3778,7 @@
   id: civ13_accessory_N34_B_body_armor
   description: >-
     A modern piece of Blugoslavian armor introduced in 2023, made fully out of
-    kevlar while also having some space left for plate inserts
+    kevlar while also having some space left for plate inserts.
   components:
     - type: Sprite
       sprite: Civ14/Clothing/exported/ties/n34bm.rsi
@@ -3778,15 +3789,9 @@
         coefficients:
           Blunt: 0.55
           Slash: 0.55
-          Piercing: 0.45
-          Arrow: 0.35
-          Heat: 0.7
-    - type: Construction
-      graph: civ13_accessory_N34_B_body_armor
-      node: end
-      cost: 5
-      material: Cloth
-      time: 5
+          Piercing: 0.55
+          Arrow: 0.3
+          Heat: 0.78
 - type: entity
   name: N34-BM body armor
   parent: civ13_accessory_N34_B_body_armor
@@ -3799,12 +3804,7 @@
       sprite: Civ14/Clothing/exported/ties/n34bmm.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/ties/n34bmm.rsi
-    - type: Construction
-      graph: civ13_accessory_N34_BM_body_armor
-      node: end
-      cost: 5
-      material: Cloth
-      time: 5
+
 - type: entity
   name: black Interceptor Body Armor
   parent: ClothingNeckBase

+ 167 - 187
Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_hats.yml

@@ -11,8 +11,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.5
-          Slash: 0.5
+          Blunt: 0.8
+          Slash: 0.8
           Piercing: 0.7
           Arrow: 0.6
           Heat: 0.40
@@ -68,9 +68,9 @@
         coefficients:
           Blunt: 0.6
           Slash: 0.6
-          Piercing: 0.55
-          Arrow: 0.55
-          Heat: 0.55
+          Piercing: 0.85
+          Arrow: 0.85
+          Heat: 0.85
 - type: entity
   name: Phase I Replicant ARF Helmet
   parent: ClothingHeadBase
@@ -87,8 +87,8 @@
           Blunt: 0.7
           Slash: 0.7
           Piercing: 0.6
-          Arrow: 0.5
-          Heat: 0.55
+          Arrow: 0.8
+          Heat: 0.85
 - type: entity
   name: Phase I Replicant Airborne Helmet
   parent: ClothingHeadBase
@@ -105,7 +105,7 @@
           Blunt: 0.65
           Slash: 0.65
           Piercing: 0.65
-          Arrow: 0.5
+          Arrow: 0.8
           Heat: 0.44
 - type: entity
   name: Stormtrooper Helmet
@@ -124,7 +124,7 @@
           Slash: 0.65
           Piercing: 0.35
           Arrow: 0.4
-          Heat: 0.5
+          Heat: 0.8
 - type: entity
   name: Storm-Surgeon Helmet
   parent: ClothingHeadBase
@@ -142,7 +142,7 @@
           Slash: 0.65
           Piercing: 0.35
           Arrow: 0.4
-          Heat: 0.5
+          Heat: 0.8
 - type: entity
   name: Stormtrooper Radio Technician Helmet
   parent: ClothingHeadBase
@@ -159,8 +159,8 @@
           Blunt: 0.7
           Slash: 0.7
           Piercing: 0.44
-          Arrow: 0.5
-          Heat: 0.5
+          Arrow: 0.8
+          Heat: 0.8
 - type: entity
   name: AT-RT Replicant Driver Helmet
   parent: ClothingHeadBase
@@ -176,9 +176,9 @@
         coefficients:
           Blunt: 0.6
           Slash: 0.6
-          Piercing: 0.55
-          Arrow: 0.55
-          Heat: 0.55
+          Piercing: 0.85
+          Arrow: 0.85
+          Heat: 0.85
 - type: entity
   name: Phase I Replicant Radio Technician Helmet
   parent: ClothingHeadBase
@@ -195,8 +195,8 @@
           Blunt: 0.7
           Slash: 0.7
           Piercing: 0.6
-          Arrow: 0.5
-          Heat: 0.5
+          Arrow: 0.8
+          Heat: 0.8
 - type: entity
   name: Replicant Engineer Helmet
   parent: ClothingHeadBase
@@ -213,8 +213,8 @@
           Blunt: 0.7
           Slash: 0.7
           Piercing: 0.6
-          Arrow: 0.5
-          Heat: 0.5
+          Arrow: 0.8
+          Heat: 0.8
           Radiation: 0.65
 - type: entity
   name: Replicant Commando Helmet
@@ -229,9 +229,9 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
-          Piercing: 0.55
+          Blunt: 0.85
+          Slash: 0.85
+          Piercing: 0.85
           Arrow: 0.35
           Heat: 0.4
 - type: entity
@@ -250,7 +250,7 @@
           Blunt: 0.7
           Slash: 0.7
           Piercing: 0.6
-          Arrow: 0.5
+          Arrow: 0.8
           Heat: 0.44
 - type: entity
   name: Phase I Replicant MP Helmet
@@ -268,8 +268,8 @@
           Blunt: 0.7
           Slash: 0.7
           Piercing: 0.6
-          Arrow: 0.5
-          Heat: 0.55
+          Arrow: 0.8
+          Heat: 0.85
 - type: entity
   name: M1 helmet 2nd LT
   parent: ClothingHeadBase
@@ -283,10 +283,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.85
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: M1 camo helmet
@@ -315,7 +315,7 @@
           Blunt: 0.7
           Slash: 0.7
           Piercing: 0.6
-          Arrow: 0.5
+          Arrow: 0.8
           Heat: 0.44
 - type: entity
   name: Phase I Replicant Commander Helmet
@@ -333,7 +333,7 @@
           Blunt: 0.7
           Slash: 0.7
           Piercing: 0.6
-          Arrow: 0.5
+          Arrow: 0.8
           Heat: 0.44
 - type: entity
   name: Phase II Replicant Trooper Helmet
@@ -407,8 +407,8 @@
           Blunt: 0.7
           Slash: 0.7
           Piercing: 0.6
-          Arrow: 0.5
-          Heat: 0.55
+          Arrow: 0.8
+          Heat: 0.85
 - type: entity
   name: roman legionary helmet
   parent: ClothingHeadBase
@@ -502,7 +502,7 @@
           Blunt: 0.4
           Slash: 0.4
           Piercing: 0.9
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: sol invictus helmet
@@ -803,8 +803,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Arrow: 0.7
           Heat: 0.85
 - type: entity
@@ -822,8 +822,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Arrow: 0.7
           Heat: 0.85
 - type: entity
@@ -841,8 +841,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.5
-          Slash: 0.5
+          Blunt: 0.8
+          Slash: 0.8
           Piercing: 0.95
           Arrow: 0.6
           Heat: 0.85
@@ -861,8 +861,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Arrow: 0.7
           Heat: 0.85
 - type: entity
@@ -938,10 +938,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.85
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: UN helmet
@@ -956,14 +956,14 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.85
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: UN medic helmet
-  parent: ClothingHeadBase
+  parent: civ13_head_UN_helmet
   id: civ13_head_UN_medic_helmet
   description: A typical blue UN helmet, with doctor markings.
   components:
@@ -998,7 +998,7 @@
         coefficients:
           Blunt: 0.4
           Slash: 0.4
-          Piercing: 0.5
+          Piercing: 0.8
           Arrow: 0.25
           Heat: 0.85
 - type: entity
@@ -1014,10 +1014,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.5
-          Slash: 0.5
+          Blunt: 0.8
+          Slash: 0.8
           Piercing: 0.85
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: Chinese helmet
@@ -1032,10 +1032,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.65
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.75
 - type: entity
   name: Medical FT1 advanced helmet
@@ -1081,10 +1081,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.85
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: white hard hat
@@ -1162,8 +1162,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.5
-          Slash: 0.5
+          Blunt: 0.8
+          Slash: 0.8
           Piercing: 0.9
           Arrow: 0.6
           Heat: 0.85
@@ -1186,8 +1186,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.8
           Arrow: 0.65
           Heat: 0.85
@@ -1210,8 +1210,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.9
           Arrow: 0.65
           Heat: 0.85
@@ -1234,8 +1234,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.5
-          Slash: 0.5
+          Blunt: 0.8
+          Slash: 0.8
           Piercing: 0.9
           Arrow: 0.6
           Heat: 0.85
@@ -1252,14 +1252,14 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.38
-          Slash: 0.38
-          Piercing: 0.44
-          Arrow: 0.25
+          Blunt: 0.8
+          Slash: 0.8
+          Piercing: 0.85
+          Arrow: 0.7
           Heat: 0.85
 - type: entity
   name: Red PASGT helmet
-  parent: ClothingHeadBase
+  parent: civ13_head_PASGT_helmet
   id: civ13_head_Red_PASGT_helmet
   description: A typical US Army PASGT helmet. This one has a red dye.
   components:
@@ -1267,14 +1267,7 @@
       sprite: Civ14/Clothing/exported/hats/pasgt_reddish.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/hats/pasgt_reddish.rsi
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.38
-          Slash: 0.38
-          Piercing: 0.44
-          Arrow: 0.25
-          Heat: 0.85
+
 - type: entity
   name: white papakha
   parent: ClothingHeadBase
@@ -1331,7 +1324,7 @@
       time: 5
 - type: entity
   name: OCP ACH helmet
-  parent: ClothingHeadBase
+  parent: civ13_head_ACH_helmet
   id: civ13_head_OCP_ACH_helmet
   description: A typical US Army Advanced Combat Helmet. This one is in OCP cammo.
   components:
@@ -1339,14 +1332,7 @@
       sprite: Civ14/Clothing/exported/hats/ach_ocp.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/hats/ach_ocp.rsi
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.25
-          Slash: 0.25
-          Piercing: 0.065
-          Arrow: 0.054
-          Heat: 0.78
+
 - type: entity
   name: ACH helmet
   parent: ClothingHeadBase
@@ -1360,11 +1346,12 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.25
-          Slash: 0.25
-          Piercing: 0.065
-          Arrow: 0.054
-          Heat: 0.78
+          Blunt: 0.8
+          Slash: 0.8
+          Piercing: 0.8
+          Arrow: 0.7
+          Heat: 0.85
+
 - type: entity
   name: MASKA 1 helmet
   parent: ClothingHeadBase
@@ -1378,10 +1365,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.1
-          Slash: 0.1
+          Blunt: 0.5
+          Slash: 0.5
           Piercing: 0.05
-          Arrow: -0.1
+          Arrow: 0.7
           Heat: 0.73
 - type: entity
   name: 6B47 helmet
@@ -1532,7 +1519,7 @@
           Slash: -0.75
           Piercing: -0.19
           Arrow: 0.010000000000000009
-          Heat: 0.58
+          Heat: 0.88
 - type: entity
   name: QGF03 helmet
   parent: ClothingHeadBase
@@ -1553,7 +1540,7 @@
           Heat: 0.85
 - type: entity
   name: M95 helmet
-  parent: ClothingHeadBase
+  parent: civ13_head_PASGT_helmet
   id: civ13_head_M95_helmet
   description: >-
     A PASGT derived helmet used by the Dutch Armed Forces. This one is in DPM
@@ -1563,14 +1550,7 @@
       sprite: Civ14/Clothing/exported/hats/m95_dpm.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/hats/m95_dpm.rsi
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.38
-          Slash: 0.38
-          Piercing: 0.44
-          Arrow: 0.25
-          Heat: 0.85
+
 - type: entity
   name: M1 Helmet
   parent: ClothingHeadBase
@@ -1584,8 +1564,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.6
-          Slash: 0.6
+          Blunt: 0.8
+          Slash: 0.8
           Piercing: 0.9
           Arrow: 0.7
           Heat: 0.85
@@ -1718,8 +1698,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.5
-          Slash: 0.5
+          Blunt: 0.8
+          Slash: 0.8
           Piercing: 0.95
           Arrow: 0.4
           Heat: 0.85
@@ -1789,8 +1769,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.9
           Arrow: 0.6
           Heat: 0.85
@@ -1995,8 +1975,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.92
           Arrow: 0.6
           Heat: 0.85
@@ -2016,8 +1996,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.92
           Arrow: 0.6
           Heat: 0.85
@@ -2207,10 +2187,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
     - type: Construction
       graph: civ13_head_italian_sallet
@@ -2233,10 +2213,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
     - type: Construction
       graph: civ13_head_german_sallet
@@ -2259,10 +2239,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
     - type: Construction
       graph: civ13_head_burgundian_sallet
@@ -2316,7 +2296,7 @@
           Blunt: 0.70
           Slash: 0.70
           Piercing: 0.9
-          Arrow: 0.5
+          Arrow: 0.8
           Heat: 0.85
 - type: entity
   name: protective conical helmet
@@ -2391,10 +2371,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.9
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: iron coif and helmet
@@ -2429,8 +2409,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
           Arrow: 0.6
           Heat: 0.85
@@ -2447,8 +2427,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
           Arrow: 0.6
           Heat: 0.85
@@ -2465,8 +2445,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
           Arrow: 0.6
           Heat: 0.85
@@ -2483,8 +2463,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
           Arrow: 0.6
           Heat: 0.85
@@ -2503,10 +2483,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: feminine long arabic helmet
@@ -2523,10 +2503,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: templar knight helmet
@@ -2561,10 +2541,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: crusader helmet
@@ -2718,10 +2698,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: royal mamluk conical helmet
@@ -2741,7 +2721,7 @@
           Blunt: 0.4
           Slash: 0.4
           Piercing: 0.9
-          Arrow: 0.5
+          Arrow: 0.8
           Heat: 0.85
 - type: entity
   name: royal viking helmet
@@ -2756,10 +2736,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: royal viking helmet
@@ -2776,10 +2756,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: varangian helmet
@@ -2816,10 +2796,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: penlianal_whitestrake helmet
@@ -2926,8 +2906,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.92
           Arrow: 0.6
           Heat: 0.85
@@ -2964,8 +2944,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.85
           Arrow: 0.7
           Heat: 0.75
@@ -2985,7 +2965,7 @@
           Blunt: 0.4
           Slash: 0.4
           Piercing: 0.9
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
 - type: entity
   name: imperial officer helmet
@@ -3003,7 +2983,7 @@
           Blunt: 0.30
           Slash: 0.30
           Piercing: 0.9
-          Arrow: 0.5
+          Arrow: 0.8
           Heat: 0.85
 - type: entity
   name: leather skullcap helmet
@@ -3041,7 +3021,7 @@
           Blunt: 0.4
           Slash: 0.4
           Piercing: 0.9
-          Arrow: 0.5
+          Arrow: 0.8
           Heat: 0.85
 - type: entity
   name: jingasa
@@ -3130,8 +3110,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.95
           Arrow: 0.35
           Heat: 0.65
@@ -3287,7 +3267,7 @@
           Piercing: 0.7
           Arrow: 0.1
           Heat: 0.8
-          Radiation: 0.55
+          Radiation: 0.85
 - type: entity
   name: orc beserker helm
   parent: ClothingHeadBase
@@ -3358,10 +3338,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.9
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
     - type: Construction
       graph: civ13_head_orc_spearman_helm
@@ -3382,10 +3362,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.44
-          Slash: 0.44
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.9
-          Arrow: 0.55
+          Arrow: 0.85
           Heat: 0.85
     - type: Construction
       graph: civ13_head_orc_captain_helm
@@ -3406,8 +3386,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.5
-          Slash: 0.5
+          Blunt: 0.8
+          Slash: 0.8
           Piercing: 0.95
           Arrow: 0.6
           Heat: 0.85
@@ -3708,8 +3688,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.57
-          Slash: 0.57
+          Blunt: 0.87
+          Slash: 0.87
           Piercing: 0.9
           Arrow: 0.66
           Heat: 0.85
@@ -3746,8 +3726,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.57
-          Slash: 0.57
+          Blunt: 0.87
+          Slash: 0.87
           Piercing: 0.9
           Arrow: 0.66
           Heat: 0.85
@@ -3767,8 +3747,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.57
-          Slash: 0.57
+          Blunt: 0.87
+          Slash: 0.87
           Piercing: 0.9
           Arrow: 0.66
           Heat: 0.85
@@ -3928,8 +3908,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.55
-          Slash: 0.55
+          Blunt: 0.85
+          Slash: 0.85
           Piercing: 0.8
           Arrow: 0.65
           Heat: 0.85
@@ -3946,8 +3926,8 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.58
-          Slash: 0.58
+          Blunt: 0.88
+          Slash: 0.88
           Piercing: 0.8
           Arrow: 0.67
           Heat: 0.85

+ 16 - 30
Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_shoes.yml

@@ -116,10 +116,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.7
-          Slash: 0.7
+          Blunt: 0.9
+          Slash: 0.9
           Piercing: 0.95
-          Arrow: 0.8
+          Arrow: 0.9
           Heat: 0.85
     - type: Construction
 
@@ -141,10 +141,10 @@
     - type: Armor
       modifiers:
         coefficients:
-          Blunt: 0.7
-          Slash: 0.7
+          Blunt: 0.9
+          Slash: 0.9
           Piercing: 0.95
-          Arrow: 0.8
+          Arrow: 0.9
           Heat: 0.85
     - type: Construction
 
@@ -206,9 +206,9 @@
       material: Leather
       time: 8
 - type: entity
-  name: military boots
+  name: military boots
   parent: ClothingShoesBase
-  id: civ13_shoes_military_boots
+  id: civ13_shoes_military_boots
   description: When you want to turn up the heat.
   components:
     - type: Sprite
@@ -225,32 +225,25 @@
           Heat: 0.75
     - type: Construction
 
-      graph: civ13_shoes_military_boots
+      graph: civ13_shoes_military_boots
       node: end
       cost: 5
       material: Cloth
       time: 5
 - type: entity
-  name: wrapped boots
+  name: wrapped boots
   parent: ClothingShoesBase
-  id: civ13_shoes_wrapped_boots
+  id: civ13_shoes_wrapped_boots
   description: ""
   components:
     - type: Sprite
       sprite: Civ14/Clothing/exported/shoes/wrappedboots.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/shoes/wrappedboots.rsi
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.19
-          Slash: 0.19
-          Arrow: 0.9
-          Heat: 0.75
-          Radiation: 0.6
+
     - type: Construction
 
-      graph: civ13_shoes_wrapped_boots
+      graph: civ13_shoes_wrapped_boots
       node: end
       cost: 5
       material: Cloth
@@ -315,14 +308,7 @@
       sprite: Civ14/Clothing/exported/shoes/japboots_ww2.rsi
     - type: Clothing
       sprite: Civ14/Clothing/exported/shoes/japboots_ww2.rsi
-    - type: Armor
-      modifiers:
-        coefficients:
-          Blunt: 0.19
-          Slash: 0.19
-          Arrow: 0.9
-          Heat: 0.75
-          Radiation: 0.6
+
     - type: Construction
 
       graph: civ13_shoes_Leather_boots
@@ -1007,7 +993,7 @@
 - type: entity
   name: military boots
   parent: ClothingShoesBase
-  id: civ13_shoes_military_boots
+  id: civ13_shoes_military_boots_tan
   description: Classic tan military boots.
   components:
     - type: Sprite
@@ -1024,7 +1010,7 @@
           Heat: 0.75
     - type: Construction
 
-      graph: civ13_shoes_military_boots
+      graph: civ13_shoes_military_boots_tan
       node: end
       cost: 5
       material: Cloth

+ 12 - 0
Resources/Prototypes/Civ14/Entities/Clothing/entities_clothing_uniform.yml

@@ -2412,6 +2412,18 @@
       cost: 5
       material: Cloth
       time: 5
+
+- type: entity
+  name: Blugoslavian officer uniform
+  parent: ClothingUniformBase
+  id: civ13_uniform_Blugoslavian_officer_uniform
+  description: A ceremonial uniform of Blugoslavia, used by officers and commanders.
+  components:
+    - type: Sprite
+      sprite: Civ14/Clothing/exported/uniforms/baf_command.rsi
+    - type: Clothing
+      sprite: Civ14/Clothing/exported/uniforms/baf_command.rsi
+
 - type: entity
   name: Blugoslavian navy uniform
   parent: ClothingUniformBase

+ 30 - 0
Resources/Prototypes/Civ14/Entities/Clothing/webbings.yml

@@ -206,3 +206,33 @@
           amount: 1
         - id: SmokeGrenadeM18
           amount: 1
+
+- type: entity
+  id: ClothingWebbingInsurgentRifleman
+  parent: ClothingWebbingGreen
+  name: green webbing
+  suffix: filled, AK47
+  components:
+    - type: StorageFill
+      contents:
+        - id: civ13_magazine_AK47_(7.62x39mm)
+          amount: 5
+        - id: GrenadeRGD5
+          amount: 1
+        - id: SmokeGrenadeRDG2
+          amount: 1
+
+- type: entity
+  id: ClothingWebbingInsurgentRifleman2
+  parent: ClothingWebbingKhaki
+  name: khaki webbing
+  suffix: filled, AK47
+  components:
+    - type: StorageFill
+      contents:
+        - id: civ13_magazine_AK47_(7.62x39mm)
+          amount: 5
+        - id: GrenadeRGD5
+          amount: 1
+        - id: SmokeGrenadeRDG2
+          amount: 1

+ 97 - 0
Resources/Prototypes/Civ14/Entities/Flora/grasses.yml

@@ -0,0 +1,97 @@
+# Yes we have decals for this, but you cannot hide under a decal can you???
+- type: entity
+  name: tall grass
+  id: WildPlantTallGrass
+  description: A patch of tall grass. Looks like a decent hiding spot.
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/bushes_dry.rsi
+      state: tall_grass_3
+      drawdepth: Overdoors
+    - type: SpriteFade
+    - type: Clickable
+    - type: Physics
+      bodyType: Static
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.17,0,0.20,0.4"
+    - type: Transform
+      anchored: true
+    - type: Damageable
+      damageContainer: StructuralInorganic
+      damageModifierSet: Wood
+    - type: Destructible
+      thresholds:
+        - trigger: !type:DamageTrigger
+            damage: 20
+          behaviors:
+            - !type:DoActsBehavior
+              acts: ["Destruction"]
+- type: entity
+  name: tall grass
+  parent: WildPlantTallGrass
+  id: WildPlantTallGrass2
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/bushes_dry.rsi
+      state: tall_grass_4
+      drawdepth: Overdoors
+- type: entity
+  name: tall grass
+  parent: WildPlantTallGrass
+  id: WildPlantTallGrass3
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/bushes_dry.rsi
+      state: tall_grass_5
+      drawdepth: Overdoors
+
+- type: entity
+  name: dry tall grass
+  parent: WildPlantTallGrass
+  id: WildPlantTallGrassDry
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/bushes_dry.rsi
+      state: tall_grass_8
+      drawdepth: Overdoors
+
+- type: entity
+  name: dry tall grass
+  parent: WildPlantTallGrassDry
+  id: WildPlantTallGrassDry2
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/bushes_dry.rsi
+      state: tall_grass_9
+      drawdepth: Overdoors
+
+- type: entity
+  name: dead tall grass
+  parent: WildPlantTallGrass
+  id: WildPlantTallGrassDead2
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/bushes_dry.rsi
+      state: dead_tall_grass_4
+      drawdepth: Overdoors
+- type: entity
+  name: dead tall grass
+  parent: WildPlantTallGrass
+  id: WildPlantTallGrassDead3
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/bushes_dry.rsi
+      state: dead_tall_grass_5
+      drawdepth: Overdoors
+- type: entity
+  name: dead tall grass
+  parent: WildPlantTallGrass
+  id: WildPlantTallGrassDead
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/bushes_dry.rsi
+      state: dead_tall_grass_3
+      drawdepth: Overdoors

+ 75 - 0
Resources/Prototypes/Civ14/Entities/Flora/warm.yml

@@ -26,6 +26,81 @@
       sprite: Civ14/Flora/bigtrees_dead.rsi
       state: african_acacia_dead
 
+- type: entity
+  parent: BaseTree
+  id: TreePalm
+  name: palm tree
+  description: A tall palm tree.
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/palms.rsi
+      layers:
+        - state: palm1
+          map: ["random"]
+    - type: RandomSprite
+      available:
+        - random:
+            palm1: ""
+            palm2: ""
+            palm1old: ""
+            palm2old: ""
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.3,-0.1,0.6,0.1"
+          density: 1000
+          layer:
+            - WallLayer
+    - type: Damageable
+      damageContainer: StructuralInorganic
+      damageModifierSet: Wood
+    - type: MeleeSound
+      soundGroups:
+        Brute:
+          path: /Audio/Effects/chop.ogg
+          params:
+            variation: 0.05
+    - type: Destructible
+      thresholds:
+        - trigger: !type:DamageTrigger
+            damage: 140
+          behaviors:
+            - !type:DoActsBehavior
+              acts: ["Destruction"]
+        - trigger: !type:DamageTrigger
+            damage: 100
+          behaviors:
+            - !type:PlaySoundBehavior
+              sound:
+                path: /Audio/Effects/tree_fell.ogg
+                params:
+                  volume: 5
+                  variation: 0.05
+            - !type:DoActsBehavior
+              acts: ["Destruction"]
+            - !type:SpawnEntitiesBehavior
+              spawn:
+                MaterialWoodPlank1:
+                  min: 2
+                  max: 3
+- type: entity
+  parent: TreePalm
+  id: TreePalmDead
+  name: dead palm tree
+  description: A tall palm tree. This one is dead.
+  components:
+    - type: Sprite
+      sprite: Civ14/Flora/palms.rsi
+      layers:
+        - state: dead_palm1
+          map: ["random"]
+    - type: RandomSprite
+      available:
+        - random:
+            dead_palm1: ""
+            dead_palm2: ""
+
 - type: decal
   id: BushJungle1
   snapCardinals: true

+ 40 - 69
Resources/Prototypes/Civ14/Entities/Markers/grace_wall.yml

@@ -29,9 +29,10 @@
             - HighImpassable
 
 - type: entity
-  name: grace wall germanyww2
-  id: MarkerGracewallGermanyWW2
+  name: grace wall factions
+  id: MarkerGracewallFaction
   parent: MarkerBase
+  abstract: true
   components:
     - type: Sprite
       sprite: Civ14/Markers/areas.rsi
@@ -39,7 +40,7 @@
     - type: GracewallArea # Use the new component
       gracewallActive: true
       gracewallRadius: 1.5
-      blockingFactions: [Germany]
+      blockingFactions: []
       permanent: true
     - type: Physics
       bodyType: Static
@@ -60,98 +61,68 @@
             - MidImpassable
             - HighImpassable
 
+- type: entity
+  name: grace wall germanyww2
+  id: MarkerGracewallGermanyWW2
+  parent: MarkerGracewallFaction
+  components:
+    - type: GracewallArea # Use the new component
+      gracewallActive: true
+      gracewallRadius: 1.5
+      blockingFactions: [Germany]
+      permanent: true
+
 - type: entity
   name: grace wall sovietww2
   id: MarkerGracewallSovietWW2
-  parent: MarkerBase
+  parent: MarkerGracewallFaction
   components:
-    - type: Sprite
-      sprite: Civ14/Markers/areas.rsi
-      state: gracewall
     - type: GracewallArea # Use the new component
       gracewallActive: true
       gracewallRadius: 1.5
       blockingFactions: [Soviet]
       permanent: true
-    - type: Physics
-      bodyType: Static
-    - type: Fixtures
-      fixtures:
-        gracewall: # Define a fixture for the area
-          shape: !type:PhysShapeAabb
-            bounds: "-0.2, -1.5, 0.2, 1.5"
-          # Collision layer/mask will be managed by the GracewallRuleSystem
-          density: 100
-          hard: true
-          mask:
-            - LowImpassable
-            - MidImpassable
-            - HighImpassable
-          layer:
-            - LowImpassable
-            - MidImpassable
-            - HighImpassable
 
 - type: entity
   name: grace wall US
   id: MarkerGracewallUS
-  parent: MarkerBase
+  parent: MarkerGracewallFaction
   components:
-    - type: Sprite
-      sprite: Civ14/Markers/areas.rsi
-      state: gracewall
     - type: GracewallArea # Use the new component
       gracewallActive: true
       gracewallRadius: 1.5
       blockingFactions: [US]
       permanent: true
-    - type: Physics
-      bodyType: Static
-    - type: Fixtures
-      fixtures:
-        gracewall: # Define a fixture for the area
-          shape: !type:PhysShapeAabb
-            bounds: "-0.2, -1.5, 0.2, 1.5"
-          # Collision layer/mask will be managed by the GracewallRuleSystem
-          density: 100
-          hard: true
-          mask:
-            - LowImpassable
-            - MidImpassable
-            - HighImpassable
-          layer:
-            - LowImpassable
-            - MidImpassable
-            - HighImpassable
 
 - type: entity
   name: grace wall sovietCW
   id: MarkerGracewallSovietCW
-  parent: MarkerBase
+  parent: MarkerGracewallFaction
   components:
-    - type: Sprite
-      sprite: Civ14/Markers/areas.rsi
-      state: gracewall
     - type: GracewallArea # Use the new component
       gracewallActive: true
       gracewallRadius: 1.5
       blockingFactions: [SovietCW]
       permanent: true
-    - type: Physics
-      bodyType: Static
-    - type: Fixtures
-      fixtures:
-        gracewall: # Define a fixture for the area
-          shape: !type:PhysShapeAabb
-            bounds: "-0.2, -1.5, 0.2, 1.5"
-          # Collision layer/mask will be managed by the GracewallRuleSystem
-          density: 100
-          hard: true
-          mask:
-            - LowImpassable
-            - MidImpassable
-            - HighImpassable
-          layer:
-            - LowImpassable
-            - MidImpassable
-            - HighImpassable
+
+- type: entity
+  name: grace wall insurgents
+  id: MarkerGracewallInsurgents
+  parent: MarkerGracewallFaction
+  components:
+    - type: GracewallArea # Use the new component
+      gracewallActive: true
+      gracewallRadius: 1.5
+      blockingFactions: [Insurgents]
+      permanent: true
+
+- type: entity
+  name: grace wall blugoslavia
+  id: MarkerGracewallBlugoslavia
+  parent: MarkerGracewallFaction
+  components:
+    - type: GracewallArea # Use the new component
+      gracewallActive: true
+      gracewallRadius: 1.5
+      blockingFactions: [Blugoslavia]
+      permanent: true

+ 66 - 1
Resources/Prototypes/Civ14/Entities/Markers/jobs.yml

@@ -25,6 +25,9 @@
       sprite: Markers/cross.rsi
       layers:
         - state: red
+        - sprite: Civ14/Objects/decals.rsi
+          state: flag_uk
+
 - type: entity
   id: SpawnPointFrench
   parent: SpawnPointJobBase
@@ -38,6 +41,9 @@
       sprite: Markers/cross.rsi
       layers:
         - state: blue
+        - sprite: Civ14/Objects/decals.rsi
+          state: flag_france
+
 - type: entity
   id: SpawnPointGerman
   parent: SpawnPointJobBase
@@ -51,6 +57,9 @@
       sprite: Markers/cross.rsi
       layers:
         - state: green
+        - sprite: Civ14/Objects/decals.rsi
+          state: flag_germany
+
 - type: entity
   id: SpawnPointSoviet
   parent: SpawnPointJobBase
@@ -64,6 +73,9 @@
       sprite: Markers/cross.rsi
       layers:
         - state: pink
+        - sprite: Civ14/Objects/decals.rsi
+          state: flag_sov
+
 - type: entity
   id: SpawnPointUS
   parent: SpawnPointJobBase
@@ -77,6 +89,9 @@
       sprite: Markers/cross.rsi
       layers:
         - state: blue
+        - sprite: Civ14/Objects/decals.rsi
+          state: flag_usa
+
 - type: entity
   id: SpawnPointSovietCW
   parent: SpawnPointJobBase
@@ -89,4 +104,54 @@
     - type: Sprite
       sprite: Markers/cross.rsi
       layers:
-        - state: pink         
+        - state: pink
+        - sprite: Civ14/Objects/decals.rsi
+          state: flag_sov
+
+- type: entity
+  id: SpawnPointInsurgents
+  parent: SpawnPointJobBase
+  name: insurgent spawner
+  suffix: faction spawn
+  components:
+    - type: SpawnPoint
+      faction: Insurgents
+      spawn_type: Faction
+    - type: Sprite
+      sprite: Markers/cross.rsi
+      layers:
+        - state: green
+        - sprite: Civ14/Objects/decals.rsi
+          state: flag_greenistan
+
+- type: entity
+  id: SpawnPointBlugoslavia
+  parent: SpawnPointJobBase
+  name: blugoslavia spawner
+  suffix: faction spawn
+  components:
+    - type: SpawnPoint
+      faction: Blugoslavia
+      spawn_type: Faction
+    - type: Sprite
+      sprite: Markers/cross.rsi
+      layers:
+        - state: blue # duh
+        - sprite: Civ14/Objects/decals.rsi
+          state: flag_blugoslavia
+
+- type: entity
+  id: SpawnPointUnitedNations
+  parent: SpawnPointJobBase
+  name: UN spawner
+  suffix: faction spawn
+  components:
+    - type: SpawnPoint
+      faction: UnitedNations
+      spawn_type: Faction
+    - type: Sprite
+      sprite: Markers/cross.rsi
+      layers:
+        - state: blue # duh
+        - sprite: Civ14/Objects/decals.rsi
+          state: flag_un

+ 113 - 0
Resources/Prototypes/Civ14/Entities/Markers/valley_areas.yml

@@ -0,0 +1,113 @@
+- type: entity
+  name: Valley Checkpoint
+  id: ValleyCheckpoint
+  parent: MarkerCapturableArea
+  components:
+    - type: Sprite
+      sprite: Civ14/Markers/areas.rsi
+      state: capture_blue
+    - type: CaptureArea
+      name: "Checkpoint"
+      captureDuration: 9999 # to make it impossibe to win by capturing
+      captureRadius: 4
+      contestedResetTime: 15 # 15 seconds before timer resets when contested
+      capturableFactions:
+        - Blugoslavia
+        - Insurgents
+    - type: ValleyCheckpoint # New component for Valley-specific logic
+
+- type: entity
+  name: Valley Western Trenches
+  id: ValleyCheckpointBravo
+  parent: ValleyCheckpoint
+  components:
+    - type: CaptureArea
+      name: "Western Trenches"
+
+- type: entity
+  name: Valley Crossroads Outpost
+  id: ValleyCheckpointCharlie
+  parent: ValleyCheckpoint
+  components:
+    - type: CaptureArea
+      name: "Crossroads Outpost"
+
+- type: entity
+  name: Valley Hill Outpost
+  id: ValleyCheckpointDelta
+  parent: ValleyCheckpoint
+  components:
+    - type: CaptureArea
+      name: "Hill Outpost"
+
+- type: entity
+  name: Insurgent Base
+  id: ValleyInsurgentBase
+  parent: MarkerCapturableArea
+  components:
+    - type: Sprite
+      sprite: Civ14/Markers/areas.rsi
+      state: capture_green
+    - type: CaptureArea
+      name: "Insurgent Base"
+      captureDuration: 9999 # to make it impossibe to win by capturing
+      captureRadius: 6
+      contestedResetTime: 15 # 15 seconds before timer resets when contested
+      capturableFactions: []
+
+- type: entity
+  name: UN Hospital
+  id: ValleyUNHospital
+  parent: MarkerCapturableArea
+  components:
+    - type: Sprite
+      sprite: Civ14/Markers/areas.rsi
+      state: capture_blue
+    - type: CaptureArea
+      name: "UN Hospital"
+      captureDuration: 9999 # to make it impossibe to win by capturing
+      captureRadius: 4
+      contestedResetTime: 15 # 15 seconds before timer resets when contested
+      capturableFactions:
+        - Blugoslavia
+        - Insurgents
+
+- type: entity
+  parent: BaseStructureDynamic
+  id: ValleySupplyBox
+  name: supply delivery
+  description: A wheeled crate with several supplies.
+  suffix: Point System
+  components:
+    - type: Sprite
+      sprite: Civ14/Objects/Storage/storage.rsi
+      state: supplybox
+    - type: ValleySupplyBox
+    - type: Physics
+      bodyType: Dynamic
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.4,-0.3,0.4,0.3"
+          density: 50
+
+- type: entity
+  id: ValleySupplyBoxSpawner
+  name: Valley Supply Box Spawner
+  parent: MarkerBase
+  components:
+    - type: Sprite
+      layers:
+        - state: blue
+        - sprite: Civ14/Objects/Storage/storage.rsi
+          state: supplybox
+        - state: timed
+    - type: Timer
+    - type: TimedSpawner
+      prototypes:
+        - ValleySupplyBox
+      chance: 1
+      intervalSeconds: 300
+      minimumEntitiesSpawned: 1
+      maximumEntitiesSpawned: 1

+ 81 - 0
Resources/Prototypes/Civ14/Entities/Mobs/NPC/civilians.yml

@@ -0,0 +1,81 @@
+- type: entity
+  name: civilian
+  parent: BaseMobHuman
+  id: MobCivilian
+  suffix: AI NPC
+  components:
+    - type: NpcFactionMember
+      factions:
+        - SimpleHostile
+    - type: Loadout
+      prototypes:
+        - Civilian1
+        - Civilian2
+        - Civilian3
+        - Civilian4
+        - Civilian5
+        - Civilian6
+        - Civilian7
+        - Civilian8
+    - type: InputMover
+    - type: MobMover
+    - type: HTN
+      rootTask:
+        task: SimpleHumanoidHostileCompound
+
+- type: startingGear
+  id: Civilian1
+  equipment:
+    jumpsuit: civ13_uniform_farmer_outfit
+    shoes: civ13_shoes_Brown_boots
+
+- type: startingGear
+  id: Civilian2
+  equipment:
+    jumpsuit: civ13_uniform_mechanic_outfit
+    shoes: civ13_shoes_Black_leather_boots
+    head: civ13_head_Afghanka_field_cap
+
+- type: startingGear
+  id: Civilian3
+  equipment:
+    jumpsuit: civ13_uniform_texan_shirt_outfit
+    shoes: civ13_shoes_Brown_boots
+    head: civ13_head_black_shemagh
+
+- type: startingGear
+  id: Civilian4
+  equipment:
+    jumpsuit: civ13_uniform_checkered_outfit
+    shoes: civ13_shoes_Black_leather_boots
+    head: civ13_head_red_cap
+
+- type: startingGear
+  id: Civilian5
+  equipment:
+    jumpsuit: civ13_uniform_pioneer_outfit
+    shoes: civ13_shoes_courier_sneakers
+    head: civ13_head_Afghanka_field_cap
+
+- type: startingGear
+  id: Civilian6
+  equipment:
+    jumpsuit: civ13_uniform_blue_colonial_clothing
+    shoes: civ13_shoes_courier_sneakers
+
+- type: startingGear
+  id: Civilian7
+  equipment:
+    jumpsuit: civ13_uniform_farmer_outfit
+    shoes: civ13_shoes_courier_sneakers
+    head: civ13_head_black_shemagh
+
+- type: startingGear
+  id: Civilian8
+  equipment:
+    jumpsuit: civ13_uniform_blue_colonial_clothing
+    shoes: civ13_shoes_Black_leather_boots
+    head: civ13_head_black_shemagh
+#shoes: civ13_shoes_Brown_boots, civ13_shoes_courier_sneakers, civ13_shoes_Black_leather_boots
+#jumpsuit: civ13_uniform_farmer_outfit, civ13_uniform_mechanic_outfit, civ13_uniform_texan_shirt_outfit, civ13_uniform_checkered_outfit, civ13_uniform_pioneer_outfit, civ13_uniform_blue_colonial_clothing
+#head: civ13_head_Afghanka_field_cap, civ13_head_red_cap, civ13_head_black_shemagh

+ 24 - 0
Resources/Prototypes/Civ14/Entities/Objects/Radio/radio_channels.yml

@@ -13,3 +13,27 @@
   frequency: 1351
   color: "#539c00"
   longRange: true
+
+- type: radioChannel
+  id: Insurgents
+  name: chat-radio-insurgents
+  keycode: "i"
+  frequency: 1352
+  color: "#539c00"
+  longRange: true
+
+- type: radioChannel
+  id: Blugoslavia
+  name: chat-radio-blugoslavia
+  keycode: "b"
+  frequency: 1353
+  color: "#0032c7"
+  longRange: true
+
+- type: radioChannel
+  id: UnitedNations
+  name: chat-radio-unitednations
+  keycode: "n"
+  frequency: 1354
+  color: "#004e9c"
+  longRange: true

+ 25 - 0
Resources/Prototypes/Civ14/Entities/Objects/Storage/filled_crates.yml

@@ -161,3 +161,28 @@
       contents:
         - id: MortarShellHE
           amount: 10
+
+# Blue wardrobe
+- type: entity
+  id: WardrobeCivMedical
+  parent: WardrobeBase
+  name: medical clothing wardrobe
+  description: "A wardrobe packed surgical clothes."
+  components:
+    - type: Appearance
+    - type: EntityStorageVisuals
+      stateBaseClosed: generic
+      stateDoorOpen: generic_open
+      stateDoorClosed: blue_door
+    - type: StorageFill
+      contents:
+        - id: ClothingHandsGlovesLatex
+          amount: 2
+        - id: ClothingMaskBreathMedical
+          amount: 2
+        - id: ClothingHeadHatSurgcapBlue
+          amount: 2
+        - id: civ13_uniform_white_medical_scrubs
+          amount: 2
+        - id: ClothingOuterCoatLabOpened
+          amount: 2

+ 23 - 0
Resources/Prototypes/Civ14/Entities/Structures/Furniture/Decorative/decoratives.yml

@@ -243,3 +243,26 @@
       cost: 8
       time: 20
       material: Stone
+
+- type: entity
+  name: traffic cone
+  parent: BaseItem
+  id: traffic cone
+  description: An orange traffic cone.
+  components:
+    - type: Sprite
+      sprite: Civ14/Objects/decals.rsi
+      state: cone
+      layers:
+        - state: cone
+          map: ["random"]
+    - type: RandomSprite
+      available:
+        - random:
+            cone: ""
+            cone1: ""
+            cone2: ""
+    - type: STWeight
+      self: 0.75
+    - type: Item
+      size: Normal

+ 88 - 3
Resources/Prototypes/Civ14/Entities/Structures/Walls/barricades.yml

@@ -419,9 +419,6 @@
       state: hescobastion
     - type: PlacementReplacement
       key: walls
-    - type: Damageable
-      damageContainer: StructuralInorganic
-      damageModifierSet: Inert
     - type: Physics
       bodyType: Static
     - type: Fixtures
@@ -519,3 +516,91 @@
       bidirectional: true
       blocking: 30
     - type: AtmosExposed
+
+- type: entity
+  parent: BaseStructure
+  id: BarricadeSandbagsTall
+  name: tall sandbag wall
+  description: A tall sandbag wall.
+  placement:
+    mode: SnapgridCenter
+    snap:
+      - Wall
+  components:
+    - type: RangedDamageSound
+      soundGroups:
+        Brute:
+          collection: MetalBulletImpact
+      soundTypes:
+        Heat:
+          collection: MetalLaserImpact
+    - type: Tag
+      tags:
+        - Wall
+    - type: Sprite
+      sprite: Civ14/Structures/barricades.rsi
+      state: sandbagfull
+      drawdepth: Walls
+    - type: Icon
+      sprite: Civ14/Structures/barricades.rsi
+      state: sandbagfull
+    - type: PlacementReplacement
+      key: walls
+    - type: Physics
+      bodyType: Static
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.49,-0.45,0.49,0.15"
+          mask:
+            - FullTileMask
+          layer:
+            - WallLayer
+          density: 1000
+    - type: Occluder
+    - type: Airtight
+      airBlocked: false
+    - type: RadiationBlocker
+      resistance: 2
+    - type: SunShadowCast
+    - type: Damageable
+      damageModifierSet: Inert
+      damageContainer: StructuralInorganic
+    - type: Destructible
+      thresholds:
+        - trigger: !type:DamageTrigger
+            damage: 450
+          behaviors:
+            - !type:DoActsBehavior
+              acts: ["Destruction"]
+
+- type: entity
+  id: BarricadeAntiTank
+  description: A static anti-tank obstacle defense made of metal angle beams.
+  parent: BaseStructure
+  name: czech hedgehog
+  components:
+    - type: InteractionOutline
+    - type: Sprite
+      sprite: Civ14/Objects/structures.rsi
+      state: antitank
+      drawdepth: BlastDoors
+      noRot: true
+    - type: Physics
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeCircle
+            radius: 0.4
+          density: 185
+          restitution: 0.0
+          mask:
+            - FullTileMask
+          layer:
+            - WallLayer
+    - type: AtmosExposed
+    - type: Climbable
+    - type: Barricade
+      bidirectional: true
+      blocking: 50

+ 62 - 0
Resources/Prototypes/Civ14/Entities/Structures/Walls/walls.yml

@@ -660,6 +660,68 @@
         - map: ["enum.EdgeLayer.West"]
           state: rocky_west
 
+- type: entity
+  id: WallRockSandIndestructible
+  parent: WallRockIndestructible
+  name: rock
+  suffix: indestructible
+  description: This wall cannot be destroyed.
+  components:
+    - type: Transform
+      noRot: true
+    - type: Airtight
+      airBlocked: true
+    - type: IconSmooth
+      key: walls
+      mode: NoSprite
+    - type: Icon
+      sprite: Structures/Walls/rock.rsi
+      state: rock_sand2
+    - type: SmoothEdge
+    - type: Sprite
+      sprite: Structures/Walls/rock.rsi
+      layers:
+        - state: rock_sand2
+        - map: ["enum.EdgeLayer.South"]
+          state: rock_sand2_south
+        - map: ["enum.EdgeLayer.East"]
+          state: rock_sand2_east
+        - map: ["enum.EdgeLayer.North"]
+          state: rock_sand2_north
+        - map: ["enum.EdgeLayer.West"]
+          state: rock_sand2_west
+
+- type: entity
+  id: WallRockSand2Indestructible
+  parent: WallRockIndestructible
+  name: rock
+  suffix: indestructible
+  description: This wall cannot be destroyed.
+  components:
+    - type: Transform
+      noRot: true
+    - type: Airtight
+      airBlocked: true
+    - type: IconSmooth
+      key: walls
+      mode: NoSprite
+    - type: Icon
+      sprite: Structures/Walls/rock.rsi
+      state: rock_sand3
+    - type: SmoothEdge
+    - type: Sprite
+      sprite: Structures/Walls/rock.rsi
+      layers:
+        - state: rock_sand3
+        - map: ["enum.EdgeLayer.South"]
+          state: rock_sand3_south
+        - map: ["enum.EdgeLayer.East"]
+          state: rock_sand3_east
+        - map: ["enum.EdgeLayer.North"]
+          state: rock_sand3_north
+        - map: ["enum.EdgeLayer.West"]
+          state: rock_sand3_west
+
 - type: entity
   parent: BaseWall
   id: AztecWall

+ 19 - 1
Resources/Prototypes/Civ14/Entities/Structures/wall_flags.yml

@@ -560,7 +560,7 @@
   components:
     - type: Sprite
       state: flag_sovborder
-      
+
 - type: entity
   id: civ13_wallflag_sov
   name: Soviet Union flag
@@ -1090,6 +1090,24 @@
     - type: Sprite
       state: flag_blugoslavia
 
+- type: entity
+  id: civ13_wallflag_yellandia
+  name: Yellandian flag
+  description: The flag of the Federation of Yellandia.
+  parent: WallFlagWhite
+  components:
+    - type: Sprite
+      state: flag_yellandia
+
+- type: entity
+  id: civ13_wallflag_greenistan
+  name: Greenistani flag
+  description: The flag of the People's Republic of Greenistan.
+  parent: WallFlagWhite
+  components:
+    - type: Sprite
+      state: flag_greenistan
+
 - type: entity
   id: civ13_wallflag_arstotzka
   name: Arstotzkan flag

+ 77 - 0
Resources/Prototypes/Civ14/Entities/teleporters.yml

@@ -0,0 +1,77 @@
+- type: entity
+  parent: LocalTeleportBase
+  id: LocalTeleportTunnelBottom
+  name: tunnel
+  components:
+    - type: Sprite
+      layers:
+        - state: hole_bottom
+      sprite: /Textures/Civ14/Objects/stairs.rsi
+    - type: LocalTeleport
+      portalName: WesternTunnel
+
+- type: entity
+  parent: LocalTeleportBase
+  id: LocalTeleportTunnelTop
+  name: tunnel
+  components:
+    - type: Sprite
+      layers:
+        - state: hole_top
+      sprite: /Textures/Civ14/Objects/stairs.rsi
+    - type: LocalTeleport
+      portalName: WesternTunnel
+
+- type: entity
+  parent: LocalTeleportBase
+  id: LocalTeleportLadderBottom
+  name: tunnel
+  components:
+    - type: Sprite
+      layers:
+        - state: ladder10
+      sprite: /Textures/Civ14/Objects/stairs.rsi
+    - type: LocalTeleport
+      portalName: WesternTunnel
+
+- type: entity
+  parent: LocalTeleportBase
+  id: LocalTeleportLadderTop
+  name: tunnel
+  components:
+    - type: Sprite
+      layers:
+        - state: ladder01
+      sprite: /Textures/Civ14/Objects/stairs.rsi
+    - type: LocalTeleport
+      portalName: WesternTunnel
+
+- type: entity
+  parent: LocalTeleportTunnelBottom
+  id: LocalTeleportTunnelBottomInsurgents
+  name: tunnel
+  suffix: Teleport, Insurgents
+  components:
+    - type: Sprite
+      layers:
+        - state: hole_bottom
+      sprite: /Textures/Civ14/Objects/stairs.rsi
+    - type: LocalTeleport
+      portalName: WesternTunnel
+    - type: AccessReader
+      access: [["Insurgents"]]
+
+- type: entity
+  parent: LocalTeleportTunnelTop
+  id: LocalTeleportTunnelTopInsurgents
+  name: tunnel
+  suffix: Teleport, Insurgents
+  components:
+    - type: Sprite
+      layers:
+        - state: hole_top
+      sprite: /Textures/Civ14/Objects/stairs.rsi
+    - type: LocalTeleport
+      portalName: WesternTunnel
+    - type: AccessReader
+      access: [["Insurgents"]]

+ 14 - 14
Resources/Prototypes/Civ14/Recipes/Clothing/recipes_clothing_shoes.yml

@@ -242,9 +242,9 @@
     - node: end
       entity: civ13_shoes_black_fur_boots
 - type: construction
-  name: military boots
-  id: civ13_shoes_military_boots
-  graph: civ13_shoes_military_boots
+  name: military boots
+  id: civ13_shoes_military_boots
+  graph: civ13_shoes_military_boots
   startNode: start
   targetNode: end
   category: construction-category-clothing
@@ -256,7 +256,7 @@
   agemin: 5
   agemax: 8
 - type: constructionGraph
-  id: civ13_shoes_military_boots
+  id: civ13_shoes_military_boots
   start: start
   graph:
     - node: start
@@ -267,11 +267,11 @@
               amount: 5
               doAfter: 5
     - node: end
-      entity: civ13_shoes_military_boots
+      entity: civ13_shoes_military_boots
 - type: construction
-  name: wrapped boots
-  id: civ13_shoes_wrapped_boots
-  graph: civ13_shoes_wrapped_boots
+  name: wrapped boots
+  id: civ13_shoes_wrapped_boots
+  graph: civ13_shoes_wrapped_boots
   startNode: start
   targetNode: end
   category: construction-category-clothing
@@ -283,7 +283,7 @@
   agemin: 5
   agemax: 8
 - type: constructionGraph
-  id: civ13_shoes_wrapped_boots
+  id: civ13_shoes_wrapped_boots
   start: start
   graph:
     - node: start
@@ -294,7 +294,7 @@
               amount: 5
               doAfter: 5
     - node: end
-      entity: civ13_shoes_wrapped_boots
+      entity: civ13_shoes_wrapped_boots
 - type: construction
   name: NCR wrapped boots
   id: civ13_shoes_NCR_wrapped_boots
@@ -1188,8 +1188,8 @@
       entity: civ13_shoes_leather_sailor_boots
 - type: construction
   name: military boots
-  id: civ13_shoes_military_boots
-  graph: civ13_shoes_military_boots
+  id: civ13_shoes_military_boots_tan
+  graph: civ13_shoes_military_boots_tan
   startNode: start
   targetNode: end
   category: construction-category-clothing
@@ -1201,7 +1201,7 @@
   agemin: 5
   agemax: 8
 - type: constructionGraph
-  id: civ13_shoes_military_boots
+  id: civ13_shoes_military_boots_tan
   start: start
   graph:
     - node: start
@@ -1212,7 +1212,7 @@
               amount: 5
               doAfter: 5
     - node: end
-      entity: civ13_shoes_military_boots
+      entity: civ13_shoes_military_boots_tan
 - type: construction
   name: black riding boots
   id: civ13_shoes_black_riding_boots

+ 243 - 0
Resources/Prototypes/Civ14/Roles/Jobs/TDM/blugoslavia.yml

@@ -0,0 +1,243 @@
+- type: job
+  id: BlugoslaviaCaptain
+  name: job-name-civ-blugoslavia-cpt
+  faction: Blugoslavia
+  originalName: Kapetan
+  description: job-description-civ-blugoslavia-cpt
+  playTimeTracker: JobBlugoslaviaCaptain
+  requirements:
+    - !type:TotalJobsTimeRequirement
+      group: CivJobsSquadLeader
+      time: 7200 # 2 hours
+  startingGear: BlugoslaviaCaptainGear
+  icon: "JobIconICpt"
+  supervisors: job-supervisors-nobody
+  ranks:
+    RankMajor:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaCaptain
+        time: 18000 # 5 hours
+    RankCaptain: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: NpcFactionMember
+          factions:
+            - Blugoslavia
+        - type: ShowFactionIcons
+          factionIcon: BlugoslaviaFaction
+          jobIcon: JobIconICpt
+          assignSquad: false
+
+- type: startingGear
+  id: BlugoslaviaCaptainGear
+  equipment:
+    shoes: civ13_shoes_jackboots
+    jumpsuit: civ13_uniform_Blugoslavian_officer_uniform
+    neck: civ13_accessory_N34_B_body_armor
+    belt: civ13_pistol_M1911A1
+    pocket2: civ13_magazine_M1911_magazine_(.45)
+    head: civ13_head_Blugoslavian_beret
+    pocket1: Compass
+    ears: ClothingHeadsetBlugoslavia
+
+# Sergeant
+
+- type: job
+  id: BlugoslaviaSergeant
+  originalName: Narednik
+  name: job-name-civ-blugoslavia-sgt
+  faction: Blugoslavia
+  description: job-description-civ-blugoslavia-sgt
+  playTimeTracker: JobBlugoslaviaSergeant
+  requirements:
+    - !type:TotalJobsTimeRequirement
+      group: CivJobsEnlisted
+      time: 7200 # 2 hours
+  startingGear: BlugoslaviaSergeantGear
+  icon: "JobIconISgt"
+  supervisors: job-supervisors-cpt
+  ranks:
+    RankSergeantMajor:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaSergeant
+        time: 36000 # 10 hours
+    RankStaffSergeant:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaSergeant
+        time: 10800 # 3 hours
+    RankSergeant: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: NpcFactionMember
+          factions:
+            - Blugoslavia
+        - type: ShowFactionIcons
+          factionIcon: BlugoslaviaFaction
+          jobIcon: JobIconISgt
+          assignSquad: true
+
+- type: startingGear
+  id: BlugoslaviaSergeantGear
+  equipment:
+    shoes: civ13_shoes_Brown_boots
+    jumpsuit: civ13_uniform_tigerstripes_camo_uniform
+    neck: civ13_accessory_N34_B_body_armor
+    head: civ13_head_Blugoslavian_beret
+    belt: civ13_pistol_M1911A1
+    pocket1: civ13_magazine_M1911_magazine_(.45)
+    pocket2: Compass
+    ears: ClothingHeadsetBlugoslavia
+  inhand:
+    - civ13_ar_AK_12
+
+# Assault Rifleman
+
+- type: job
+  id: BlugoslaviaRifleman
+  name: job-name-civ-blugoslavia-rifleman
+  faction: Blugoslavia
+  originalName: Puškar
+  description: job-description-civ-blugoslavia-rifleman
+  playTimeTracker: JobBlugoslaviaRifleman
+  startingGear: BlugoslaviaRiflemanGear
+  randomStartingGears: [BlugoslaviaRiflemanGear]
+  icon: "JobIconICpl"
+  supervisors: job-supervisors-cpt
+  ranks:
+    RankLanceCorporal:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaRifleman
+        time: 36000 # 10 hours
+    RankPrivateFirstClass:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaRifleman
+        time: 10800 # 3 hours
+    RankPrivate: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: NpcFactionMember
+          factions:
+            - Blugoslavia
+        - type: ShowFactionIcons
+          factionIcon: BlugoslaviaFaction
+          jobIcon: JobIconRifleman
+          assignSquad: true
+
+- type: startingGear
+  id: BlugoslaviaRiflemanGear
+  equipment:
+    shoes: civ13_shoes_Brown_boots
+    jumpsuit: civ13_uniform_tigerstripes_camo_uniform
+    neck: civ13_accessory_N34_B_body_armor
+    head: civ13_head_ACH_helmet
+    belt: ClothingWebbingSovietCWRifleman
+    pocket1: FlashlightLanternMilitary
+    pocket2: Gauze
+    ears: ClothingHeadsetBlugoslavia
+  inhand:
+    - civ13_ar_AK_12
+
+# Machinegunner
+
+- type: job
+  id: BlugoslaviaMachinegunner
+  name: job-name-civ-blugoslavia-machinegunner
+  faction: Blugoslavia
+  originalName: Mitraljezac
+  description: job-description-civ-blugoslavia-machinegunner
+  playTimeTracker: JobBlugoslaviaMachinegunner
+  startingGear: BlugoslaviaMachinegunnerGear
+  randomStartingGears: [BlugoslaviaMachinegunnerGear]
+  icon: "JobIconMg"
+  supervisors: job-supervisors-cpt
+  requirements:
+    - !type:TotalJobsTimeRequirement
+      group: CivJobsEnlisted
+      time: 3600 # 1 hours
+  ranks:
+    RankLanceCorporal:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaMachinegunner
+        time: 36000 # 10 hours
+    RankPrivateFirstClass:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaMachinegunner
+        time: 10800 # 3 hours
+    RankPrivate: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: NpcFactionMember
+          factions:
+            - Blugoslavia
+        - type: ShowFactionIcons
+          factionIcon: BlugoslaviaFaction
+          jobIcon: JobIconMg
+          assignSquad: true
+
+- type: startingGear
+  id: BlugoslaviaMachinegunnerGear
+  equipment:
+    shoes: civ13_shoes_Brown_boots
+    jumpsuit: civ13_uniform_tigerstripes_camo_uniform
+    gloves: ClothingHandsGlovesFingerless
+    belt: ClothingWebbingSovietCWMG
+    neck: civ13_accessory_N34_B_body_armor
+    head: civ13_head_ACH_helmet
+    pocket1: CombatKnife
+    pocket2: Gauze
+    ears: ClothingHeadsetBlugoslavia
+  inhand:
+    - civ13_mg_RPD_machine_gun
+
+# Medic
+
+- type: job
+  id: BlugoslaviaMedic
+  name: job-name-civ-blugoslavia-medic
+  faction: Blugoslavia
+  originalName: Sanitarnik
+  description: job-description-civ-blugoslavia-medic
+  playTimeTracker: JobBlugoslaviaMedic
+  startingGear: BlugoslaviaMedicGear
+  icon: "JobIconMedic"
+  supervisors: job-supervisors-cpt
+  requirements:
+    - !type:TotalJobsTimeRequirement
+      group: CivJobsEnlisted
+      # time: 9000 # 2.5 hours
+      time: 3600 # 1 hour temporarily until people build up playtime
+  ranks:
+    RankSergeant:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaMedic
+        time: 10800 # 3 hours
+    RankCorporal: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: NpcFactionMember
+          factions:
+            - Blugoslavia
+        - type: ShowFactionIcons
+          factionIcon: BlugoslaviaFaction
+          jobIcon: JobIconMedic
+          assignSquad: false
+
+- type: startingGear
+  id: BlugoslaviaMedicGear
+  equipment:
+    shoes: civ13_shoes_Brown_boots
+    jumpsuit: civ13_uniform_tigerstripes_camo_uniform
+    neck: civ13_accessory_N34_BM_body_armor
+    head: civ13_head_ACH_helmet
+    belt: ClothingSatchelMedicalMedsFilled
+    back: ClothingBackpackDuffelFilled
+    pocket1: FlashlightLanternMilitary
+    pocket2: civ13_magazine_AK_74_magazine_(5.45x39mm)
+    ears: ClothingHeadsetBlugoslavia
+  inhand:
+    - civ13_ar_AK_12

+ 188 - 0
Resources/Prototypes/Civ14/Roles/Jobs/TDM/insurgent.yml

@@ -0,0 +1,188 @@
+# Leader
+
+- type: job
+  id: InsurgentLeader
+  originalName: Qaynarqan
+  name: job-name-civ-insurgent-sgt
+  faction: Insurgents
+  description: job-description-civ-insurgent-sgt
+  playTimeTracker: JobInsurgentLeader
+  requirements:
+    - !type:TotalJobsTimeRequirement
+      group: CivJobsEnlisted
+      time: 7200 # 2 hours
+  startingGear: InsurgentLeaderGear
+  icon: "JobIconISgt"
+  supervisors: job-supervisors-nobody
+  ranks:
+    RankSergeantMajor:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaSergeant
+        time: 36000 # 10 hours
+    RankStaffSergeant:
+      - !type:RoleTimeRequirement
+        role: JobBlugoslaviaSergeant
+        time: 10800 # 3 hours
+    RankSergeant: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: NpcFactionMember
+          factions:
+            - Insurgents
+        - type: ShowFactionIcons
+          factionIcon: GreenistanFaction
+          jobIcon: JobIconISgt
+          assignSquad: true
+        - type: Access
+          groups:
+            - Insurgents
+
+- type: startingGear
+  id: InsurgentLeaderGear
+  equipment:
+    shoes: civ13_shoes_black_boots
+    jumpsuit: civ13_uniform_black_tunic_with_desert_camo_trousers
+    neck: civ13_accessory_khaki_PASGT_body_armor
+    head: civ13_head_black_bandana
+    belt: civ13_sword_saif
+    pocket1: civ13_magazine_AK_74_magazine_(5.45x39mm)
+    pocket2: Compass
+    ears: ClothingHeadsetInsurgents
+  inhand:
+    - civ13_ar_AK_74
+
+# Assault Rifleman
+
+- type: job
+  id: InsurgentRifleman
+  name: job-name-civ-insurgent-rifleman
+  faction: Insurgents
+  originalName: Tufangchy
+  description: job-description-civ-insurgent-rifleman
+  playTimeTracker: JobInsurgentRifleman
+  startingGear: InsurgentRiflemanGear
+  randomStartingGears: [InsurgentRiflemanGear, InsurgentRiflemanGear2, InsurgentRiflemanGear3]
+  icon: "JobIconICpl"
+  supervisors: job-supervisors-sgt
+  ranks:
+    RankLanceCorporal:
+      - !type:RoleTimeRequirement
+        role: JobInsurgentRifleman
+        time: 36000 # 10 hours
+    RankPrivateFirstClass:
+      - !type:RoleTimeRequirement
+        role: JobInsurgentRifleman
+        time: 10800 # 3 hours
+    RankPrivate: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: NpcFactionMember
+          factions:
+            - Insurgents
+        - type: ShowFactionIcons
+          factionIcon: GreenistanFaction
+          jobIcon: JobIconRifleman
+          assignSquad: true
+        - type: Access
+          groups:
+            - Insurgents
+
+- type: startingGear
+  id: InsurgentRiflemanGear
+  equipment:
+    shoes: civ13_shoes_black_boots
+    jumpsuit: civ13_uniform_sand_colored_tunic_with_woodland_camo_trousers
+    neck: civ13_accessory_khaki_PASGT_body_armor
+    head: civ13_head_black_bandana
+    mask: civ13_mask_black_balaclava
+    belt: ClothingWebbingInsurgentRifleman2
+    pocket1: FlashlightLanternMilitary
+    pocket2: Gauze
+    ears: ClothingHeadsetInsurgents
+  inhand:
+    - civ13_ar_AKM
+
+- type: startingGear
+  id: InsurgentRiflemanGear2
+  equipment:
+    shoes: civ13_shoes_Soviet_sapogi_boots
+    jumpsuit: civ13_uniform_sand_colored_uniform_with_desert_camo_trousers
+    gloves: ClothingHandsGlovesFingerless
+    belt: ClothingWebbingInsurgentRifleman
+    neck: civ13_accessory_green_PASGT_body_armor
+    head: civ13_head_black_shemagh
+    pocket1: FlashlightLanternMilitary
+    pocket2: Gauze
+    ears: ClothingHeadsetInsurgents
+  inhand:
+    - civ13_ar_AKM
+
+- type: startingGear
+  id: InsurgentRiflemanGear3
+  equipment:
+    shoes: civ13_shoes_Soviet_sapogi_boots
+    jumpsuit: civ13_uniform_light_brown_uniform_with_green_trousers
+    gloves: ClothingHandsGlovesFingerless
+    belt: ClothingWebbingInsurgentRifleman2
+    neck: civ13_accessory_woodland_PASGT_body_armor
+    head: civ13_head_black_shemagh
+    mask: civ13_mask_black_balaclava
+    pocket1: FlashlightLanternMilitary
+    pocket2: Gauze
+    ears: ClothingHeadsetInsurgents
+  inhand:
+    - civ13_ar_AKM
+
+# Medic
+
+- type: job
+  id: InsurgentMedic
+  name: job-name-civ-insurgent-medic
+  faction: Insurgents
+  originalName: Shifobash
+  description: job-description-civ-insurgent-medic
+  playTimeTracker: JobInsurgentMedic
+  startingGear: InsurgentMedicGear
+  icon: "JobIconMedic"
+  supervisors: job-supervisors-sgt
+  requirements:
+    - !type:TotalJobsTimeRequirement
+      group: CivJobsEnlisted
+      # time: 9000 # 2.5 hours
+      time: 3600 # 1 hour temporarily until people build up playtime
+  ranks:
+    RankSergeant:
+      - !type:RoleTimeRequirement
+        role: JobInsurgentMedic
+        time: 10800 # 3 hours
+    RankCorporal: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: NpcFactionMember
+          factions:
+            - Insurgents
+        - type: ShowFactionIcons
+          factionIcon: GreenistanFaction
+          jobIcon: JobIconMedic
+          assignSquad: false
+        - type: Access
+          groups:
+            - Insurgents
+
+- type: startingGear
+  id: InsurgentMedicGear
+  equipment:
+    shoes: civ13_shoes_Soviet_sapogi_boots
+    jumpsuit: civ13_uniform_Soviet_uniform
+    neck: civ13_accessory_green_PASGT_body_armor
+    head: civ13_head_black_shemagh
+    belt: ClothingSatchelMedicalMedsFilled
+    back: ClothingBackpackDuffelFilled
+    pocket1: FlashlightLanternMilitary
+    pocket2: civ13_magazine_AK47_(7.62x39mm)
+    ears: ClothingHeadsetInsurgents
+  inhand:
+    - civ13_ar_AKM

+ 34 - 0
Resources/Prototypes/Civ14/Roles/Jobs/TDM/playtimetrackers.yml

@@ -1,3 +1,31 @@
+# modern
+- type: playTimeTracker
+  id: JobInsurgentLeader
+
+- type: playTimeTracker
+  id: JobInsurgentRifleman
+
+- type: playTimeTracker
+  id: JobInsurgentMachinegunner
+
+- type: playTimeTracker
+  id: JobInsurgentMedic
+
+- type: playTimeTracker
+  id: JobBlugoslaviaCaptain
+
+- type: playTimeTracker
+  id: JobBlugoslaviaSergeant
+
+- type: playTimeTracker
+  id: JobBlugoslaviaRifleman
+
+- type: playTimeTracker
+  id: JobBlugoslaviaMachinegunner
+
+- type: playTimeTracker
+  id: JobBlugoslaviaMedic
+
 # coldwar
 - type: playTimeTracker
   id: JobSovietCWCaptain
@@ -138,3 +166,9 @@
 
 - type: playTimeTracker
   id: JobFrenchMedic
+
+- type: playTimeTracker
+  id: JobUnitedNationsMedic
+
+- type: playTimeTracker
+  id: JobUnitedNationsRifleman

+ 115 - 0
Resources/Prototypes/Civ14/Roles/Jobs/TDM/unitedNations.yml

@@ -0,0 +1,115 @@
+- type: job
+  id: UnitedNationsRifleman
+  name: job-name-civ-unitednations-rifleman
+  faction: UnitedNations
+  originalName: Rifleman
+  description: job-description-civ-unitednations-rifleman
+  playTimeTracker: JobUnitedNationsRifleman
+  startingGear: UnitedNationsRiflemanGear
+  randomStartingGears: [UnitedNationsRiflemanGear, UnitedNationsRiflemanGear2]
+  icon: "JobIconICpl"
+  supervisors: job-supervisors-nobody
+  requirements:
+    - !type:TotalJobsTimeRequirement
+      group: CivJobsEnlisted
+      # time: 9000 # 2.5 hours
+      time: 3600 # 1 hour temporarily until people build up playtime
+  ranks:
+    RankLanceCorporal:
+      - !type:RoleTimeRequirement
+        role: JobUnitedNationsRifleman
+        time: 36000 # 10 hours
+    RankPrivateFirstClass:
+      - !type:RoleTimeRequirement
+        role: JobUnitedNationsRifleman
+        time: 10800 # 3 hours
+    RankPrivate: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: NpcFactionMember
+          factions:
+            - UnitedNations
+        - type: ShowFactionIcons
+          factionIcon: UnitedNationsFaction
+          jobIcon: JobIconRifleman
+          assignSquad: true
+
+- type: startingGear
+  id: UnitedNationsRiflemanGear
+  equipment:
+    shoes: civ13_shoes_jackboots
+    jumpsuit: civ13_uniform_woodland_camo_uniform
+    neck: civ13_accessory_un_PASGT_body_armor
+    head: civ13_head_UN_helmet
+    belt: ClothingWebbingUSCWRifleman
+    pocket1: FlashlightLanternMilitary
+    pocket2: Gauze
+    ears: ClothingHeadsetUnitedNations
+  inhand:
+    - civ13_ar_M16A2
+
+- type: startingGear
+  id: UnitedNationsRiflemanGear2
+  equipment:
+    shoes: civ13_shoes_jackboots
+    jumpsuit: civ13_uniform_woodland_camo_uniform
+    gloves: ClothingHandsGlovesFingerless
+    belt: ClothingWebbingUSCWRifleman
+    neck: civ13_accessory_un_PASGT_body_armor
+    head: civ13_head_UN_beret
+    pocket1: FlashlightLanternMilitary
+    pocket2: Gauze
+    ears: ClothingHeadsetUnitedNations
+  inhand:
+    - civ13_ar_M16A2
+
+# Medic
+
+- type: job
+  id: UnitedNationsMedic
+  name: job-name-civ-unitednations-medic
+  faction: UnitedNations
+  originalName: Medic
+  description: job-description-civ-unitednations-medic
+  playTimeTracker: JobUnitedNationsMedic
+  startingGear: UnitedNationsMedicGear
+  icon: "JobIconMedic"
+  supervisors: job-supervisors-nobody
+  requirements:
+    - !type:TotalJobsTimeRequirement
+      group: CivJobsEnlisted
+      # time: 9000 # 2.5 hours
+      time: 3600 # 1 hour temporarily until people build up playtime
+  ranks:
+    RankSergeant:
+      - !type:RoleTimeRequirement
+        role: JobUnitedNationsMedic
+        time: 10800 # 3 hours
+    RankCorporal: []
+  special:
+    - !type:AddComponentSpecial
+      components:
+        - type: RussianAccent
+        - type: NpcFactionMember
+          factions:
+            - UnitedNations
+        - type: ShowFactionIcons
+          factionIcon: UnitedNationsFaction
+          jobIcon: JobIconMedic
+          assignSquad: false
+
+- type: startingGear
+  id: UnitedNationsMedicGear
+  equipment:
+    shoes: civ13_shoes_jackboots
+    jumpsuit: civ13_uniform_woodland_camo_uniform
+    neck: civ13_accessory_un_PASGT_body_armor
+    head: civ13_head_UN_medic_helmet
+    belt: ClothingSatchelMedicalMedsFilled
+    back: ClothingBackpackDuffelFilled
+    pocket1: FlashlightLanternMilitary
+    pocket2: civ13_magazine_STANAG_magazine_(5.56x45mm)
+    ears: ClothingHeadsetUnitedNations
+  inhand:
+    - civ13_ar_M16A2

+ 32 - 1
Resources/Prototypes/Civ14/Roles/Jobs/departments.yml

@@ -80,4 +80,35 @@
     - SovietCWSergeant
     - SovietCWRifleman
     - SovietCWMachinegunner
-    - SovietCWMedic
+    - SovietCWMedic
+
+- type: department
+  id: DepInsurgents
+  name: department-Insurgents
+  description: department-Insurgents-description
+  color: "#24a600"
+  roles:
+    - InsurgentLeader
+    - InsurgentRifleman
+    - InsurgentMedic
+
+- type: department
+  id: DepBlugoslavia
+  name: department-Blugoslavia
+  description: department-Blugoslavia-description
+  color: "#002fca"
+  roles:
+    - BlugoslaviaCaptain
+    - BlugoslaviaSergeant
+    - BlugoslaviaRifleman
+    - BlugoslaviaMachinegunner
+    - BlugoslaviaMedic
+
+- type: department
+  id: DepUnitedNations
+  name: department-UnitedNations
+  description: department-UnitedNations-description
+  color: "#3a62e7"
+  roles:
+    - UnitedNationsRifleman
+    - UnitedNationsMedic

+ 13 - 0
Resources/Prototypes/Civ14/Roles/Jobs/jobgroups.yml

@@ -17,6 +17,10 @@
         - GermanRifleman
         - GermanMachinegunner
         - GermanSubmachineGunner
+        - BlugoslaviaRifleman
+        - BlugoslaviaMachinegunner
+        - InsurgentRifleman
+        - UnitedNationsRifleman
 
 - type: entity
   id: CivJobsEnlistedRifleman
@@ -31,6 +35,9 @@
         - SovietRifleman
         - USRifleman
         - GermanRifleman
+        - InsurgentRifleman
+        - BlugoslaviaRifleman
+        - UnitedNationsRifleman
 
 - type: entity
   id: CivJobsMedical
@@ -45,6 +52,9 @@
         - SovietCWMedic
         - USMedic
         - GermanMedic
+        - InsurgentMedic
+        - BlugoslaviaMedic
+        - UnitedNationsMedic
 
 - type: entity
   id: CivJobsSquadLeader
@@ -59,6 +69,8 @@
         - SovietCWSergeant
         - USSergeant
         - GermanSergeant
+        - InsurgentLeader
+        - BlugoslaviaSergeant
 
 - type: entity
   id: CivJobsOfficer
@@ -73,3 +85,4 @@
         - SovietCWCaptain
         - USCaptain
         - GermanCaptain
+        - BlugoslaviaCaptain

+ 12 - 1
Resources/Prototypes/Civ14/StatusIcon/faction.yml

@@ -224,6 +224,17 @@
     sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
     state: greek_basic
 
+- type: factionIcon
+  id: GreenistanFaction
+  priority: 1
+  showTo:
+    components:
+      - ShowAntagIcons
+      - ShowFactionIcons
+  icon:
+    sprite: /Textures/Interface/Misc/civ_hud_countries.rsi
+    state: greenistan
+
 - type: factionIcon
   id: HezFaction
   priority: 1
@@ -610,7 +621,7 @@
     state: ukr_basic
 
 - type: factionIcon
-  id: UnFaction
+  id: UnitedNationsFaction
   priority: 1
   showTo:
     components:

+ 45 - 0
Resources/Prototypes/Entities/Clothing/Ears/headsets.yml

@@ -82,3 +82,48 @@
       sprite: Civ14/Objects/headset.rsi
     - type: Clothing
       sprite: Civ14/Objects/headset.rsi
+
+- type: entity
+  parent: ClothingHeadset
+  id: ClothingHeadsetInsurgents
+  name: Insurgent headset
+  description: A headset used by the Insurgents.
+  components:
+    - type: ContainerFill
+      containers:
+        key_slots:
+          - EncryptionKeyInsurgents
+    - type: Sprite
+      sprite: Civ14/Objects/headset.rsi
+    - type: Clothing
+      sprite: Civ14/Objects/headset.rsi
+
+- type: entity
+  parent: ClothingHeadset
+  id: ClothingHeadsetBlugoslavia
+  name: Blugoslavia headset
+  description: A headset used by the Republic of Blugoslavia.
+  components:
+    - type: ContainerFill
+      containers:
+        key_slots:
+          - EncryptionKeyBlugoslavia
+    - type: Sprite
+      sprite: Civ14/Objects/headset.rsi
+    - type: Clothing
+      sprite: Civ14/Objects/headset.rsi
+
+- type: entity
+  parent: ClothingHeadset
+  id: ClothingHeadsetUnitedNations
+  name: UN headset
+  description: A headset used by the United Nations.
+  components:
+    - type: ContainerFill
+      containers:
+        key_slots:
+          - EncryptionKeyUnitedNations
+    - type: Sprite
+      sprite: Civ14/Objects/headset.rsi
+    - type: Clothing
+      sprite: Civ14/Objects/headset.rsi

+ 13 - 0
Resources/Prototypes/Entities/Markers/Spawners/mobs.yml

@@ -834,3 +834,16 @@
     - type: ConditionalSpawner
       prototypes:
         - MobReindeerDoe
+
+- type: entity
+  name: civilian NPC spawner
+  id: SpawnCivilian
+  parent: MarkerBase
+  components:
+    - type: Sprite
+      layers:
+        - state: green
+        - state: ai
+    - type: ConditionalSpawner
+      prototypes:
+        - MobCivilian

+ 48 - 0
Resources/Prototypes/Entities/Objects/Devices/encryption_keys.yml

@@ -55,3 +55,51 @@
       layers:
         - state: crypt_gray
         - state: common_label
+
+- type: entity
+  parent: EncryptionKey
+  id: EncryptionKeyBlugoslavia
+  name: Blugoslavia encryption key
+  description: An encryption key used by the Republic of Blugoslavia.
+  components:
+    - type: EncryptionKey
+      channels:
+        - Common
+        - Blugoslavia
+      defaultChannel: Blugoslavia
+    - type: Sprite
+      layers:
+        - state: crypt_blue
+        - state: common_label
+
+- type: entity
+  parent: EncryptionKey
+  id: EncryptionKeyInsurgents
+  name: Insurgent encryption key
+  description: An encryption key used by the Insurgents.
+  components:
+    - type: EncryptionKey
+      channels:
+        - Common
+        - Insurgents
+      defaultChannel: Insurgents
+    - type: Sprite
+      layers:
+        - state: crypt_gray
+        - state: common_label
+
+- type: entity
+  parent: EncryptionKey
+  id: EncryptionKeyUnitedNations
+  name: United Nations encryption key
+  description: An encryption key used by the United Nations.
+  components:
+    - type: EncryptionKey
+      channels:
+        - Common
+        - UnitedNations
+      defaultChannel: UnitedNations
+    - type: Sprite
+      layers:
+        - state: crypt_blue
+        - state: common_label

+ 50 - 0
Resources/Prototypes/Entities/Structures/Walls/asteroid.yml

@@ -738,6 +738,56 @@
         - map: ["enum.EdgeLayer.West"]
           state: rocky_west
 
+- type: entity
+  id: WallRockSand2
+  parent: WallRock
+  name: rock
+  suffix: planetmap
+  description: Its made of large, uneven rocks stacked together.
+  components:
+    - type: Icon
+      sprite: Structures/Walls/rock.rsi
+      state: rock_sand2
+    - type: MiningScannerViewable
+    - type: SmoothEdge
+    - type: Sprite
+      sprite: Structures/Walls/rock.rsi
+      layers:
+        - state: rock_sand2
+        - map: ["enum.EdgeLayer.South"]
+          state: rock_sand2_south
+        - map: ["enum.EdgeLayer.East"]
+          state: rock_sand2_east
+        - map: ["enum.EdgeLayer.North"]
+          state: rock_sand2_north
+        - map: ["enum.EdgeLayer.West"]
+          state: rock_sand2_west
+
+- type: entity
+  id: WallRockSand3
+  parent: WallRock
+  name: rock
+  suffix: planetmap
+  description: Its made of large, uneven rocks stacked together.
+  components:
+    - type: Icon
+      sprite: Structures/Walls/rock.rsi
+      state: rock_sand3
+    - type: MiningScannerViewable
+    - type: SmoothEdge
+    - type: Sprite
+      sprite: Structures/Walls/rock.rsi
+      layers:
+        - state: rock_sand3
+        - map: ["enum.EdgeLayer.South"]
+          state: rock_sand3_south
+        - map: ["enum.EdgeLayer.East"]
+          state: rock_sand3_east
+        - map: ["enum.EdgeLayer.North"]
+          state: rock_sand3_north
+        - map: ["enum.EdgeLayer.West"]
+          state: rock_sand3_west
+
 # Ore veins
 - type: entity
   id: WallRockCoal

+ 42 - 44
Resources/Prototypes/Entities/Structures/base_structure.yml

@@ -4,27 +4,26 @@
   placement:
     mode: SnapgridCenter
   components:
-  - type: Transform
-    anchored: true
-  - type: Clickable
-  - type: Physics
-    bodyType: Static
-  - type: Fixtures
-    fixtures:
-      fix1:
-        shape:
-          !type:PhysShapeAabb
-          bounds: "-0.45,-0.45,0.45,0.45"
-        density: 60
-        mask:
-        - MachineMask
-        layer:
-        - MidImpassable
-        - LowImpassable
-  - type: Pullable
-  - type: Tag
-    tags:
-      - Structure
+    - type: Transform
+      anchored: true
+    - type: Clickable
+    - type: Physics
+      bodyType: Static
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.45,-0.45,0.45,0.45"
+          density: 60
+          mask:
+            - MachineMask
+          layer:
+            - MidImpassable
+            - LowImpassable
+    - type: Pullable
+    - type: Tag
+      tags:
+        - Structure
 
 - type: entity
   # This means that it's not anchored on spawn.
@@ -32,29 +31,28 @@
   parent: BaseStructure
   abstract: true
   components:
-# These might/might not be a good idea
-#  - type: MovedByPressure
-#  - type: DamageOnHighSpeedImpact
-#  - type: TileFrictionModifier
-#    modifier: 0.5
-  - type: Transform
-    anchored: false
-  - type: Clickable
-  - type: Physics
-    bodyType: Dynamic
-  - type: Fixtures
-    fixtures:
-      fix1:
-        shape:
-          !type:PhysShapeAabb
-          bounds: "-0.45,-0.45,0.45,0.45"
-        density: 60
-        mask:
-        - MachineMask
-        layer:
-        - MidImpassable
-        - LowImpassable
-  - type: Anchorable
+    # These might/might not be a good idea
+    #  - type: MovedByPressure
+    #  - type: DamageOnHighSpeedImpact
+    #  - type: TileFrictionModifier
+    #    modifier: 0.5
+    - type: Transform
+      anchored: false
+    - type: Clickable
+    - type: Physics
+      bodyType: Dynamic
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.45,-0.45,0.45,0.45"
+          density: 60
+          mask:
+            - MachineMask
+          layer:
+            - MidImpassable
+            - LowImpassable
+    - type: Anchorable
 
 # For use with yaml composition, so that all wheeled structures can easily be changed.
 - type: entity

+ 15 - 1
Resources/Prototypes/GameRules/roundstart.yml

@@ -22,7 +22,7 @@
     - type: RespawnDeadRule
       alwaysRespawnDead: true
     - type: RespawnTracker
-      respawnDelay: 120
+      respawnDelay: 180
       deleteBody: false
 # A fixed timer where all reinforcements are spawned at the same time.
 - type: entity
@@ -92,6 +92,14 @@
       timer: 40
       defenderFactionName: SovietCW
 
+- type: entity
+  parent: BaseGameRule
+  id: CaptureAreaRulePoints
+  components:
+    - type: CaptureAreaRule
+      mode: Points
+      pointsFactionName1: Blugoslavia
+
 - type: entity
   id: TeamDeathMatchRule
   parent: BaseGameRule
@@ -118,3 +126,9 @@
     - type: RandomWeatherRule
       allowedWeathers: ["SnowfallLight"]
       dayTimes: ["Night"]
+
+- type: entity
+  parent: BaseGameRule
+  id: ValleyPointsRule
+  components:
+    - type: ValleyPoints

+ 1 - 1
Resources/Prototypes/Guidebook/nomads.yml

@@ -1,7 +1,7 @@
 - type: guideEntry
   id: Nomads
   name: guide-entry-nomads
-  priority: 0
+  priority: 2
   text: "/ServerInfo/Guidebook/Nomads/nomads.xml"
   children:
     - NomadsStarterGuide

+ 1 - 1
Resources/Prototypes/Guidebook/rules.yml

@@ -2,7 +2,7 @@
   id: DefaultRuleset
   name: guide-entry-rules
   ruleEntry: true
-  priority: 10
+  priority: 1
   text: "/ServerInfo/Guidebook/ServerRules/DefaultRules.xml"
   children:
     - RuleC1

+ 4 - 4
Resources/Prototypes/Guidebook/station.yml

@@ -5,11 +5,11 @@
   text: "/ServerInfo/Guidebook/SpaceStation14.xml"
   children:
     - References
-    - Glossary
     - Medical
     - Species
+    - Mapping
 
 - type: guideEntry
-  id: Glossary
-  name: guide-entry-glossary
-  text: "/ServerInfo/Guidebook/Glossary.xml"
+  id: Mapping
+  name: guide-entry-mapping
+  text: "/ServerInfo/Guidebook/Mapping.xml"

+ 13 - 0
Resources/Prototypes/Guidebook/tdm.yml

@@ -0,0 +1,13 @@
+- type: guideEntry
+  id: TDM
+  name: guide-entry-tdm
+  priority: 3
+  text: "/ServerInfo/Guidebook/TDM/tdm.xml"
+  children:
+    - TDMValley
+
+- type: guideEntry
+  id: TDMValley
+  name: guide-entry-valley
+  priority: 1
+  text: "/ServerInfo/Guidebook/TDM/valley.xml"

+ 32 - 0
Resources/Prototypes/Maps/civ/valley.yml

@@ -0,0 +1,32 @@
+- type: gameMap
+  id: Valley
+  mapName: "Valley (Modern)"
+  mapPath: /Maps/civ/tdm/valley.yml
+  minPlayers: 10
+  maxPlayers: 200
+  maxRandomOffset: 0
+  randomRotation: false
+  fixedPreset: TDMValley
+  stations:
+    Valley:
+      stationProto: StandardStationTDM
+      components:
+        - type: StationNameSetup
+          mapNameTemplate: "Valley (Modern)"
+        - type: StationJobs
+          availableJobs:
+            # Insurgents
+            InsurgentLeader: [6, 6]
+            InsurgentRifleman: [60, 60]
+            InsurgentMedic: [4, 4]
+
+            # Blugoslavia
+            BlugoslaviaCaptain: [1, 1]
+            BlugoslaviaSergeant: [4, 4]
+            BlugoslaviaRifleman: [50, 50]
+            BlugoslaviaMachinegunner: [5, 5]
+            BlugoslaviaMedic: [3, 3]
+
+            # UN
+            UnitedNationsMedic: [3, 3]
+            UnitedNationsRifleman: [5, 5]

+ 4 - 4
Resources/Prototypes/Tiles/floors.yml

@@ -1721,8 +1721,8 @@
     - 1.0
     - 1.0
     - 1.0
-  baseTurf: Space
-  isSubfloor: true
+  baseTurf: FloorDirt
+  isSubfloor: false
   footstepSounds:
     collection: FootstepAsteroid
   heatCapacity: 10000
@@ -1741,8 +1741,8 @@
     - 1.0
     - 1.0
     - 1.0
-  baseTurf: Space
-  isSubfloor: true
+  baseTurf: FloorPlanetDryDirt
+  isSubfloor: false
   footstepSounds:
     collection: FootstepAsteroid
   heatCapacity: 10000

+ 35 - 0
Resources/Prototypes/_Stalker/Entities/Objects/base.yml

@@ -0,0 +1,35 @@
+- type: entity
+  id: BaseShippingContainer
+  abstract: true
+  placement:
+    mode: SnapgridCenter
+  components:
+    - type: SpriteFade
+    - type: Clickable
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/containers.rsi
+      netsync: false
+      drawdepth: Overdoors
+    - type: Physics
+      bodyType: Static
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-1.5,0.5,1.5,-1"
+          density: 1000
+          layer:
+            - WallLayer
+    - type: Damageable
+      damageContainer: Inorganic
+      damageModifierSet: Metallic
+    - type: Destructible
+      thresholds:
+        - trigger: !type:DamageTrigger
+            damage: 500
+          behaviors:
+            - !type:PlaySoundBehavior
+              sound:
+                collection: MetalBreak
+            - !type:DoActsBehavior
+              acts: ["Destruction"]

+ 123 - 0
Resources/Prototypes/_Stalker/Entities/Objects/containers.yml

@@ -0,0 +1,123 @@
+- type: entity
+  id: ContainerBoxStalker
+  parent: BaseShippingContainer
+  name: shipping container
+  description: This type of sea container is typically used for transporting large and bulky cargo, up to 9 meters in length. One of the main advantages of this container is its increased height, which allows for transporting more cargo at the same freight cost.
+  suffix: ST
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/containers.rsi
+      state: donk_co
+
+- type: entity
+  id: ContainerBoxStalkerRandom
+  parent: ContainerBoxStalker
+  name: shipping container
+  suffix: ST, Random
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/containers.rsi
+      layers:
+        - state: donk_co
+          map: ["random"]
+    - type: RandomSprite
+      available:
+        - random:
+            donk_co: ""
+            conarex: ""
+            cybersun: ""
+            deforest: ""
+            gorlex: ""
+            gorlex_red: ""
+            interdyne: ""
+            kahraman: ""
+            kahraman_alt: ""
+            kosmologistika: ""
+            nakamura: ""
+            nanotrasen: ""
+            nthi: ""
+            vitezstvi: ""
+
+- type: entity
+  id: ContainerStalkerParent
+  parent: BaseShippingContainer
+  abstract: true
+  name: container parent
+  suffix: ST
+  components:
+    - type: Physics
+      bodyType: Static
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.9,0.9,1.9,-0.9"
+          density: 1000
+          layer:
+            - WallLayer
+
+- type: entity
+  id: ContainerBlueStalker
+  parent: ContainerStalkerParent
+  name: blue container
+  description: This type of sea container is typically used for transporting large and bulky cargo, up to 9 meters in length. One of the main advantages of this container is its increased height, which allows for transporting more cargo at the same freight cost.
+  suffix: ST
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/containerss.rsi
+      state: blue_clear
+
+- type: entity
+  id: ContainerBlueRustedStalker
+  parent: ContainerStalkerParent
+  name: blue rusty container
+  description: This type of sea container is typically used for transporting large and bulky cargo, up to 9 meters in length. One of the main advantages of this container is its increased height, which allows for transporting more cargo at the same freight cost. The container is completely covered in rust.
+  suffix: ST
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/containerss.rsi
+      state: blue_rusted
+
+- type: entity
+  id: ContainerRedStalker
+  parent: ContainerStalkerParent
+  name: red container
+  description: This type of sea container is typically used for transporting large and bulky cargo, up to 9 meters in length. One of the main advantages of this container is its increased height, which allows for transporting more cargo at the same freight cost.
+  suffix: ST
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/containerss.rsi
+      state: red_clear
+
+- type: entity
+  id: ContainerRedRustedStalker
+  parent: ContainerStalkerParent
+  name: red rusty container
+  description: This type of sea container is typically used for transporting large and bulky cargo, up to 9 meters in length. One of the main advantages of this container is its increased height, which allows for transporting more cargo at the same freight cost. The container is completely covered in rust.
+  suffix: ST
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/containerss.rsi
+      state: red_rusted
+
+- type: entity
+  id: ContainerYellowStalker
+  parent: ContainerStalkerParent
+  name: yellow container
+  description: This type of sea container is typically used for transporting large and bulky cargo, up to 9 meters in length. One of the main advantages of this container is its increased height, which allows for transporting more cargo at the same freight cost.
+  suffix: ST
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/containerss.rsi
+      state: yellow_clear
+
+- type: entity
+  id: ContainerYellowRustedStalker
+  parent: ContainerStalkerParent
+  name: yellow rusty container
+  description: This type of sea container is typically used for transporting large and bulky cargo, up to 9 meters in length. One of the main advantages of this container is its increased height, which allows for transporting more cargo at the same freight cost. The container is completely covered in rust.
+  suffix: ST
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/containerss.rsi
+      state: yellow_rusted

+ 422 - 0
Resources/Prototypes/_Stalker/Entities/Objects/transport.yml

@@ -0,0 +1,422 @@
+# Вертолет
+- type: entity
+  id: helicopterStructure
+  parent: BaseShippingContainer
+  name: broken helicopter
+  suffix: Decorative
+  description: Crashed as a result of a disaster, the model is unknown.
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/helicopter.rsi
+      scale: 0.8, 0.8
+      state: h1
+    - type: Physics
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.3,-1.4,0.8,1.5"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+
+# брошенная машина
+
+- type: entity
+  id: STForgottenCar
+  parent: OldCarGreen
+  name: abandoned car
+  description: How old is this monument to the automotive industry, and how many rock paintings are on it?
+  suffix: STCar, Decorative
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/forgotten_car.rsi
+      state: base
+
+# УАЗ (БУХАНКА)
+
+- type: entity
+  id: UAZStructure
+  parent: BaseShippingContainer
+  name: UAZ-452
+  suffix: STCar, Decorative
+  description: A family of four-wheel drive off-road vans and light trucks with a body on a frame and a cabin above the engine, produced by the Ulyanovsk Automobile Plant (UAZ) since 1965.
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/uaz.rsi
+      scale: 0.8, 0.8
+      state: base
+    - type: Physics
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-1.5,-0.9,1.5,0.9"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+    - type: Damageable
+      damageContainer: Inorganic
+      damageModifierSet: Metallic
+    - type: Destructible
+      thresholds:
+        - trigger: !type:DamageTrigger
+            damage: 500
+          behaviors:
+            - !type:PlaySoundBehavior
+              sound:
+                collection: MetalBreak
+            - !type:DoActsBehavior
+              acts: ["Destruction"]
+
+- type: entity
+  id: UAZStructureRusted
+  parent: UAZStructure
+  name: rusty UAZ-452
+  suffix: STCar, Decorative
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/uaz.rsi
+      state: rusted
+# СТАРЫЕ МАШИНЫ (сломанные и тп)
+
+- type: entity
+  id: OldCarGreen
+  parent: BaseShippingContainer
+  name: old green car
+  suffix: STCar, Decorative
+  description: It's a pretty old car, made back in Soviet times. Time spares no one, that's why she's in such a bad state. Unfortunately, it is impossible to distinguish the make of the car. At least, you don't know them.
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/old_cars.rsi
+      scale: 0.8, 0.8
+      state: old_car_green
+    - type: Physics
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.6,-1.1,0.6,1.1"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+    - type: Damageable
+      damageContainer: Inorganic
+      damageModifierSet: Metallic
+    - type: Destructible
+      thresholds:
+        - trigger: !type:DamageTrigger
+            damage: 500
+          behaviors:
+            - !type:PlaySoundBehavior
+              sound:
+                collection: MetalBreak
+            - !type:DoActsBehavior
+              acts: ["Destruction"]
+
+- type: entity
+  id: OldCarRed
+  parent: OldCarGreen
+  name: old red car
+  suffix: STCar, Decorative
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/old_cars.rsi
+      scale: 0.8, 0.8
+      state: old_car_red
+
+- type: entity
+  id: CarRedUS
+  parent: OldCarGreen
+  name: old red imported car
+  suffix: STCar, Decorative
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/old_cars.rsi
+      scale: 0.8, 0.8
+      state: car_red_us
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.7,-1.4,0.6,1.3"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+
+- type: entity
+  id: CarGreenUS
+  parent: OldCarGreen
+  name: old green imported car
+  suffix: STCar, Decorative
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/old_cars.rsi
+      scale: 0.8, 0.8
+      state: car_green_us
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.7,-1.4,0.6,1.3"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+
+- type: entity
+  id: BrokenCarGreen
+  parent: OldCarGreen
+  name: old wrecked car
+  suffix: STCar, Decorative
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/old_cars.rsi
+      scale: 0.8, 0.8
+      state: niva_broken
+
+- type: entity
+  id: BrokenCarRed
+  parent: OldCarGreen
+  name: old wrecked car
+  suffix: STCar, Decorative
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/old_cars.rsi
+      scale: 0.8, 0.8
+      state: linkoln_broken
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.7,-1.4,0.6,1.3"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+
+# ЗИЛы
+
+- type: entity
+  id: ZIL
+  parent: BaseShippingContainer
+  name: ZIL-130
+  suffix: STCar, Decorative
+  description: A Soviet and Russian medium-tonnage truck of the third generation developed and manufactured by the Likhachev Automobile Plant in Moscow.
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/zil.rsi
+      scale: 1.1, 1.1
+      state: z1
+    - type: Physics
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.7,-1.9,1.0,1.9"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+    - type: Damageable
+      damageContainer: Inorganic
+      damageModifierSet: Metallic
+    - type: Destructible
+      thresholds:
+        - trigger: !type:DamageTrigger
+            damage: 500
+          behaviors:
+            - !type:PlaySoundBehavior
+              sound:
+                collection: MetalBreak
+            - !type:DoActsBehavior
+              acts: ["Destruction"]
+- type: entity
+  id: ZIL2
+  parent: ZIL
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/zil.rsi
+      scale: 1.1, 1.1
+      state: z2
+
+# ЛОДКИ
+
+- type: entity
+  id: boatStalker1
+  parent: BaseShippingContainer
+  name: boat
+  suffix: Decorative
+  description: A small deckless vessel.
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/boat1.rsi
+      scale: 0.8, 0.8
+      state: b2
+    - type: InteractionOutline
+    - type: Physics
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.5,-0.8,0.5,0.8"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+
+- type: entity
+  id: boatStalker2
+  name: motor boat
+  parent: boatStalker1
+  description: A small deckless vessel with a motor.
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/boat2.rsi
+      scale: 0.8, 0.8
+      state: b1
+    - type: InteractionOutline
+    - type: Physics
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.5,-0.8,0.5,0.8"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+
+# МОСКВИЧ
+
+- type: entity
+  id: Moskvich
+  parent: BaseShippingContainer
+  name: Moskvich-412
+  suffix: STCar, Decorative
+  description: A Soviet and Russian rear-wheel drive car of the II group of small class, produced from October 1967 to 1976 at the MZMA plant.
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/moskvich.rsi
+      scale: 0.8, 0.8
+      state: m1
+    - type: InteractionOutline
+    - type: Physics
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.6,-1.0,0.6,0.8"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+    - type: Damageable
+      damageContainer: Inorganic
+      damageModifierSet: Metallic
+    - type: Destructible
+      thresholds:
+        - trigger: !type:DamageTrigger
+            damage: 500
+          behaviors:
+            - !type:PlaySoundBehavior
+              sound:
+                collection: MetalBreak
+            - !type:DoActsBehavior
+              acts: ["Destruction"]
+
+# КРАЗ
+
+- type: entity
+  id: kraz
+  name: KrAZ-260
+  description: A three-axle large-tonnage off-road truck designed for cargo transportation. The awning was repainted for military needs.
+  parent: ZIL
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/kraz.rsi
+      state: kraz1
+
+- type: entity
+  id: kraz2
+  name: KrAZ-260
+  description: A three-axle large-tonnage off-road truck designed for cargo transportation.
+  parent: kraz
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/kraz.rsi
+      state: kraz2
+
+# Icarus
+
+- type: entity
+  id: icarus
+  name: ikarus-280
+  description: Hungarian urban articulated high-floor medium-drive bus with extra large capacity from Ikarus.
+  parent: kraz
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/icarus.rsi
+      state: icarus
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.8,-2.7,0.7,2.9"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+
+# Танк
+
+- type: entity
+  id: STtank
+  parent: kraz
+  name: Tank
+  suffix: Decorative
+  description: An armored combat vehicle, with cannon and additional machine-gun armament mounted in a rotating full-turn turret.
+  components:
+    - type: Sprite
+      sprite: _Stalker/Objects/Decoration/Transport/tank.rsi
+      scale: 0.9, 0.9
+      state: tank_one
+    - type: Physics
+    - type: Fixtures
+      fixtures:
+        fix1:
+          shape: !type:PhysShapeAabb
+            bounds: "-1.2,-1.9,1.4,2.2"
+          density: 155
+          mask:
+            - MachineMask
+          layer:
+            - WallLayer
+    - type: Damageable
+      damageContainer: Inorganic
+      damageModifierSet: Metallic
+    - type: Destructible
+      thresholds:
+        - trigger: !type:DamageTrigger
+            damage: 1000
+          behaviors:
+            - !type:PlaySoundBehavior
+              sound:
+                collection: MetalBreak
+            - !type:DoActsBehavior
+              acts: ["Destruction"]

+ 54 - 0
Resources/Prototypes/_Stalker/teleporters.yml

@@ -0,0 +1,54 @@
+- type: entity
+  id: STBaseTeleport
+  abstract: true
+  suffix: Teleport
+  components:
+    - type: Transform
+      anchored: True
+    - type: Physics
+      bodyType: Static
+    - type: Fixtures
+      fixtures:
+        portalFixture:
+          shape: !type:PhysShapeAabb
+            bounds: "-0.5,-0.5,0.5,0.5"
+          mask:
+            - FullTileMask
+          layer:
+            - TableLayer
+          hard: false
+    - type: InteractionOutline
+    - type: Clickable
+
+- type: entity
+  parent: STBaseTeleport
+  id: LocalTeleportBase
+  abstract: true
+  components:
+    - type: Sprite # I think you'll need to add an invisibility here
+      layers:
+        - state: hole_bottom
+      sprite: /Textures/Civ14/Objects/stairs.rsi
+    - type: LocalTeleport
+
+- type: entity
+  parent: STBaseTeleport
+  id: LocalTeleportBaseUncollide
+  abstract: true
+  components:
+    - type: Sprite # I think you'll need to add an invisibility here
+      layers:
+        - state: hole_bottom
+      sprite: /Textures/Civ14/Objects/stairs.rsi
+    - type: LocalTeleport
+# Portal system template
+
+# Example:
+# - type: entity
+#   parent: LocalTeleportBase
+#   id: LocalTeleportMilBase1
+#   tag: Stalker 1
+#   name: Военная база 1
+#   components:
+#     - type: LocalTeleport
+#       portalName: MilBase1

+ 59 - 4
Resources/Prototypes/ai_factions.yml

@@ -236,7 +236,7 @@
     - Predator
     - Germany
     - US
-    
+
 - type: npcFaction
   id: Germany
   hostile:
@@ -251,7 +251,7 @@
     - Predator
     - Soviet
     - US
-     
+
 - type: npcFaction
   id: US
   hostile:
@@ -264,7 +264,7 @@
     - AllHostile
     - Wizard
     - Predator
-    - Soviet  
+    - Soviet
     - Germany
 
 - type: npcFaction
@@ -280,4 +280,59 @@
     - Wizard
     - Predator
     - Germany
-    - US
+    - US
+
+- type: npcFaction
+  id: Insurgents
+  hostile:
+    - SimpleHostile
+    - Syndicate
+    - Xeno
+    - Zombie
+    - Revolutionary
+    - Dragon
+    - AllHostile
+    - Wizard
+    - Predator
+    - US
+    - Blugoslavia
+
+- type: npcFaction
+  id: Blugoslavia
+  hostile:
+    - SimpleHostile
+    - Syndicate
+    - Xeno
+    - Zombie
+    - Revolutionary
+    - Dragon
+    - AllHostile
+    - Wizard
+    - Predator
+    - Insurgents
+
+- type: npcFaction
+  id: UnitedNations
+  hostile:
+    - SimpleHostile
+    - Syndicate
+    - Xeno
+    - Zombie
+    - Revolutionary
+    - Dragon
+    - AllHostile
+    - Wizard
+    - Predator
+
+- type: npcFaction
+  id: Civilian
+  hostile:
+    - SimpleHostile
+    - Syndicate
+    - Xeno
+    - Zombie
+    - Revolutionary
+    - Dragon
+    - AllHostile
+    - Wizard
+    - Predator

+ 15 - 0
Resources/Prototypes/game_presets.yml

@@ -37,3 +37,18 @@
     - CaptureAreaRuleAsymmetric
     - TeamDeathMatchRule
     - RandomWeatherRuleNightSnow
+
+- type: gamePreset
+  id: TDMValley
+  alias:
+    - tdm-valley
+  name: tdm-valley-title
+  showInVote: true
+  description: tdm-valley-description
+  rules:
+    - RespawnDeadRuleTDM
+    - GracewallRule
+    - ValleyPointsRule
+    - TeamDeathMatchRule
+    - RandomWeatherRule
+    - CaptureAreaRulePoints

+ 1 - 10
Resources/Prototypes/radio_channels.yml

@@ -16,17 +16,8 @@
 - type: radioChannel
   id: Binary
   name: chat-radio-binary
-  keycode: "b"
+  keycode: "f"
   frequency: 1001
   color: "#5ed7aa"
   # long range since otherwise it'd defeat the point of a handheld radio independent of telecomms
   longRange: true
-
-- type: radioChannel
-  id: Freelance
-  name: chat-radio-freelance
-  keycode: "f"
-  frequency: 1984
-  color: "#f6ce64"
-  # long range since otherwise it'd defeat the point of a handheld radio independent of telecomms
-  longRange: true

+ 0 - 191
Resources/ServerInfo/Guidebook/Glossary.xml

@@ -1,191 +0,0 @@
-<Document>
-# Glossary
-
-This page contains most slang terms you might encounter on the station and throughout the community !
-
-# In-Character Slang
-
-These are terms you might encounter in-game.
-
-## AOS
-Arrest on sight.
-
-## AA
-All Access, or an ID which has every access on the station. The captain is the only person who will have this kind of access under normal circumstances.
-
-## Atmos
-Short for Atmospherics.
-
-## Atmosian
-A term for Atmospheric Technicians, or generally anyone who spends most of their time or is particularly skilled with Atmospherics.
-
-## Bolted
-An airlock that will never change states. It will stay permanently open or permanently closed until it is unbolted. Closed and bolted airlocks have solid red lights.
-
-## Borg
-Short for cyborgs, player-controlled robots.
-
-## Braindead
-Refers to a user who has disconnected from the game. Disconnected users may still reconnect to the server and assume control of their character again.
-
-## Brig
-The main area of the security department. This is where prisoners are brought and held for their punishment. The Warden is in charge of the brig's smooth operation.
-
-## Cap
-Short for Captain.
-
-## Cargonia
-Reference to cargo declaring independence. Against the rules.
-
-## CE
-Short for Chief Engineer, the head of the Engineering Department.
-
-## CentComm/Central Command
-An administrative agency which oversees the Nanotrasen space station you inhabit.
-
-## CMO
-Short for Chief Medical Officer, the head of the Medical Department.
-
-## Crit/Critical
-Refers to the health state at which you fall unconscious and unable to move. While in critical, your health slowly decays until you die, unless you happen to get outside assistance.
-
-## Emag
-  Refers to the Syndicate cryptographic sequencer. "Emagged" usually refers to airlocks or lockers that are bolted open, but also any other device hacked into by an Emag.
-
-## Emergency Access/EA
-  An airlock that can be opened by anyone, even without access or an ID at all. Airlocks that are set to emergency access have blinking yellow lights.
-
-## ERT
-An Emergency Response Team. These may be dispatched by Central Command for a number of purposes.
-
-## Flukie
-A portmanteau of "Fluke" and "Nukie" used to (usually derogatorily) refer to a team of Nuclear Operatives who fail their objective. May also appear as "Fluke Ops".
-
-## God(s)
-An IC term representing a Server Administrator. CentComm is also sometimes used in this manner.
-
-## Greytide/Greyshirt/Tider/Assistant
-Typically utilized to refer to a Passenger due to the color of their standard uniform, though this may be used to negatively refer to other crew members (not only passengers) who act unruly or commit various minor crimes.
-
-## HoP
-Short for Head of Personnel, head of the Service Department. Can also refer to the HoP's office, where IDs are given or changed.
-
-## HoS
-Short for Head of Security, head of the Security Department.
-
-## Insuls
-Short for Insulated Gloves. These are the yellow gloves most often worn by Engineers. They are offer complete protection from getting electrocuted from shocked things. Vastily more effective than their budget variety.
-
-## Jani
-Short for Janitor.
-
-## KOS
-Kill on sight. Someone has commited such a serious crime that they are deemed not even worth arresting.
-
-## Mats
-Materials. Usually steel, plastic, plasteel, glass, silver and gold.
-
-## Nanotrasen/NT
-Nanotrasen is the company which owns the space station you inhabit.
-
-## Newkie
-A portmanteau of "New" and "Nukie" used to refer to an inexperienced player in the role of a Nuclear Operative.
-
-## Nukie
-A slang/shorthand term of a Nuclear Operative. May sometimes also appear as "Nuke Op".
-
-## Perma
-Short for Permanent Brig. This is for the most serious crime and means that a prisoner will never be released. Most stations have a dedicated, separate area of security for the permanent brig.
-
-## QM
-Short for Quartermaster, the head of the Cargo department.
-
-## RD
-Short for Research Director, the head of the Science Department.
-
-## Robust
-A word used to describe someone who is particularly adept in combat, or endured through a tough fight.
-
-## Salv
-Short for Salvage tech.
-
-## Sci
-Short for Science.
-
-## Sec
-Short for Security.
-
-## Secoff
-Short for Security Officer.
-
-## Shift
-In-Character way to refer to rounds.
-
-## Singulo
-A shortening of the Singularity Engine. A Singulo can create infinite power for the station but is very dangerous.
-
-## Singuloose
-A Singularity that has grownth too much and breached it's containment. It will rip through the station causing massive damage.
-
-## Spacing
-An event which causes an area to lose air pressure, i.e. a hull breach.
-
-## Spess
-An intentional mis-spelling of "Space", sometimes used as a portmanteau of "space" and "mess". May also appear in words such as "Spessmen".
-
-## SSD
-Short for Sudden Sleep Disorder or Space Sleep Disorder. This is an in-character way to refer to a player who has disconnected and is no longer responding.
-
-## Syndie/Syndi/Syndicate
-A catch-all reference to anyone employed by the Syndicate. This ranges from (suspected) Syndicate Agents to Nuclear Operatives.
-
-## TC
-A telecrystal, which is a currency used by Syndicate Agents to purchase restricted contraband such as weapons and other illegal equipment.
-
-## Wardenloose
-A joke term referencing a Singuloose. A wardenloose is when the Warden is seen outside of the brig.
-
-## Xenoarchaeology
-Study of artifacts, usually performed by science.
-
-# Out-Of-Character Slang
-
-These are terms you should only be using in OOC chat or outside the game.
-
-## Admeme
-An event hosted or caused by an admin.
-
-## AHelp/Admin Help
-A relay used to report rulebreaking behavior or other issues to administrators.
-
-## Antag
-Short for Antagonists, which are specifically picked individuals designed to drive the round into chaos.
-
-## Bwoink
-The noise made when an admin-help is received. Pray this isn't a ban.
-
-## Ick Ock
-A phrase usually shouted in OOC when somebody reveals IC current round information, or "in-character, out-of-character".
-
-## LOOC/OOC
-Local out-of-character and (global) out-of-character respectively. They are text channels that allow players to talk to other players outside of roleplay. LOOC is enabled during rounds, while OOC is typically only on after the round ends.
-
-## LRP
-Low Roleplay. Servers marked LRP typically have relaxed roleplaying rules.
-
-## MRP
-Medium Roleplay. Servers marked MRP usually have a decent basis of roleplaying rules and generally require players to act as their character would realistically in a given situation. Less leeway is afforded to behavior such as openly defying Security or your boss.
-
-## HRP
-High Roleplay. Servers marked HRP generally have extensive rules on what is and is not constituted while playing a character. You are generally required to act as your character would, have a character backstory, and follow protocol on the station. Some HRP servers may create their own lore or settings to further facilitate the type of server they wish to host.
-
-## Self-Antag
-A term for a player who engages in antagonist-like activity without actually being an antagonist. This encompasses a wide variety of behavior, but is typically used to describe annoying behavior or actions which are greatly detrimental to other players for no purpose. Self-antagonism is a bannable offense. Sometimes used in IC. DO NOT DO THIS.
-
-## Upstream
-The baseline version of the game. Any changes to Upstream will "flow" down to all other forks of the game. All official Wizard's Den servers work off of Upstream.
-
-## Validhunter
-A player who hunts down "valids", as in people that are valid to kill, even though this person isn't security.
-
-</Document>

+ 29 - 0
Resources/ServerInfo/Guidebook/Mapping.xml

@@ -0,0 +1,29 @@
+<Document>
+# Guide to Mapping
+
+For the full guide with a tutorial, please check the wiki.
+
+## The TL;DR
+
+Here is a quick rundown of the steps you need to go through to make a new map, in case you need a refresher or you're already familiar with the mapping process. Otherwise, scroll down to the tutorial.
+
+1. When you're ingame, spawn as an observer. Open the console using backslash key and type [color=orange]mapping 10 Maps/civ/template.yml[/color]. This will open the template map, which has some presets predefined.
+
+2. Expand the map if you need to, first select a floor tile and hold CTRL and drag it to expand. Remember to enclose the new area in indestructible walls, normally [color=orange]WallRockIndestructible[/color]. If you do so, remember to run [color=orange]fixgridatmos[/color] in the console.
+
+3. Map to your heart's content. Don't forget to add:
+
+    - Spawns for all factions
+    - An observer spawn somewhere
+    - Capturable area(s), if applicable
+    - Grace walls
+
+4. Save the map using [color=orange]savemap 10 mapname.yml[/color]. The file will be created in [color=orange]bin/Content.Server/Data[/color]. Move it to the map folder in [color=orange]Resources/[/color] afterwards.
+
+5. Create a new map metadata in [color=orange]Resources/Prototypes/Maps[/color] and edit it accordingly. Don't forget to define an ID, the preset and the jobs.
+
+6. Edit the map file and add the ID you defined above to the station section.
+
+7. [bold]Test it!![/bold]
+
+</Document>

+ 43 - 0
Resources/ServerInfo/Guidebook/TDM/tdm.xml

@@ -0,0 +1,43 @@
+<Document>
+# Team Deathmatch
+
+## Gamemodes
+
+Even though all Team Death Match game modes feature two or more teams fighting eachother, there are different victory conditions. They can be broadly divided into Symmetric, Asymmetric, King-of-the-Hill and Points-Based. These will be detailed below.
+
+### Symmetric
+
+This could also be called classic, in this game mode each team has to defend their base and capture the opponents'.
+
+### Asymmetric
+
+Basically siege mode - one team has to defend a point for X minutes, while the attacker has to capture this point for Y minutes to win.
+
+### King of the Hill
+
+All teams compete to capture a single objective. This is normally located in the centre of the map.
+
+### Points-based
+
+Each team has different conditions they need to meet in order to win. This is highly map-specific, it could be gaining points from holding an area, for kills, for capturing enemies, and so on.
+
+## Current Maps
+
+Below is a list of the current maps, and a brief description:
+
+### Medieval
+
+-   [bold]Camp:[/bold] A small KotH map. French and English soldiers compete for the control of a castle, located in the centre of the map.
+
+### WW2
+
+-   [bold]Opushka:[/bold] A small KotH map. Germans and Soviets fight for the control of a ruined house in the centre of the map.
+
+### Cold War
+
+-   [bold]Hotel:[/bold] A medium-sized Asymmetric map. The Soviets defend a command post located in a Hotel in the Ural mountains, which the Americans have to assault.
+
+### Modern
+
+-   [bold]Valley:[/bold] A medium-sized, tactical point-based map set in the fictional universe of the Blugoslavian-Redmenian conflict, Blugoslavian forces fighting Greenistani insurgents while the UN watches. Has its own article, [textlink="Valley" link="TDMValley"].
+</Document>

+ 26 - 0
Resources/ServerInfo/Guidebook/TDM/valley.xml

@@ -0,0 +1,26 @@
+<Document>
+  # Valley
+[bold]Valley[/bold] is a fictional modern-era map, designed for tactical combat and deep role-playing (RP). Set in the Blugoslavia-Redmenia universe of Civ13, focusing on a conflict-ravaged border region, it pits organized military forces against local insurgents, with a neutral UN presence adding complexity. The map emphasizes strategy, terrain mastery, and faction-specific objectives, making every skirmish a test of wits and coordination.
+
+
+## Victory Conditions
+
+### Blugoslavia
+
+Blugoslavia earns points through logistical and territorial control to secure the Valley. Victory is achieved by reaching [bold][color=cyan]1000 points[/color][/bold] or having the most points when the match timer (50 minutes) expires.
+
+-   [bold]Supply Box Deliveries[/bold]: Transport supply boxes from the FOB to any of the four checkpoints. Each delivery earns [bold][color=cyan]50 points[/color][/bold]. Boxes must be secured at a checkpoint uncontested for 30 seconds.
+-   [bold]Holding Checkpoints[/bold]: Control a checkpoint (no insurgents in its radius) to earn [bold][color=cyan]5 points[/color] per checkpoint per minute[/bold]. Holding all four checkpoints simultaneously grants a [bold][color=cyan]100-point bonus[/color][/bold] every 5 minutes.
+
+### Greenistani Insurgents
+
+Insurgents earn points by eliminating Blugoslavian forces, disrupting their operations. Victory is achieved by reaching [bold][color=cyan]1000 points[/color][/bold] or having the most points when the match timer (50 minutes) expires.
+
+-   [bold]Kills[/bold]: Earn [bold][color=cyan]30 points[/color][/bold] per Blugoslavian soldier killed.
+-   [bold]Disrupting Operations[/bold]: Additional points may be earned by stealing supply boxes and bringing them to the base: [bold][color=cyan]75 points[/color] per box[/bold]. Destroying boxes earns no points but denies the enemy theirs.
+
+### United Nations
+
+The UN cannot "win" the scenario per se, but their own independent objectives are ensuring 80% civilian NPC survival rate and maintain control of the hospital zone without violating neutrality.
+
+</Document>

BIN
Resources/Textures/Civ14/Clothing/exported/ties/pasgt_un.rsi/equipped-NECK.png


BIN
Resources/Textures/Civ14/Clothing/exported/ties/pasgt_un.rsi/icon.png


+ 23 - 0
Resources/Textures/Civ14/Clothing/exported/ties/pasgt_un.rsi/meta.json

@@ -0,0 +1,23 @@
+{
+    "version": 1,
+    "license": "AGPLv3",
+    "copyright": "Taken from Civilization 13 https://github.com/civ13/civ13",
+    "size": {
+        "x": 32,
+        "y": 32
+    },
+    "states": [
+        {
+            "name": "pasgt_un",
+            "directions": 1
+        },
+        {
+            "name": "equipped-NECK",
+            "directions": 4
+        },
+        {
+            "name": "icon",
+            "directions": 1
+        }
+    ]
+}

BIN
Resources/Textures/Civ14/Clothing/exported/ties/pasgt_un.rsi/pasgt_un.png


BIN
Resources/Textures/Civ14/Flora/palms.rsi/dead_palm1.png


BIN
Resources/Textures/Civ14/Flora/palms.rsi/dead_palm2.png


+ 29 - 0
Resources/Textures/Civ14/Flora/palms.rsi/meta.json

@@ -0,0 +1,29 @@
+{
+    "version": 1,
+    "license": "AGPLv3",
+    "copyright": "Taken from Civilization 13 https://github.com/civ13/civ13",
+    "size": {
+        "x": 32,
+        "y": 64
+    },
+    "states": [
+        {
+            "name": "palm1old"
+        },
+        {
+            "name": "palm2old"
+        },
+        {
+            "name": "palm1"
+        },
+        {
+            "name": "palm2"
+        },
+        {
+            "name": "dead_palm1"
+        },
+        {
+            "name": "dead_palm2"
+        }
+    ]
+}

BIN
Resources/Textures/Civ14/Flora/palms.rsi/palm1.png


BIN
Resources/Textures/Civ14/Flora/palms.rsi/palm1old.png


BIN
Resources/Textures/Civ14/Flora/palms.rsi/palm2.png


BIN
Resources/Textures/Civ14/Flora/palms.rsi/palm2old.png


+ 567 - 564
Resources/Textures/Civ14/Objects/Storage/storage.rsi/meta.json

@@ -1,566 +1,569 @@
 {
-  "version": 1,
-  "license": "AGPLv3",
-  "copyright": "Taken from Civilization 13 https://github.com/civ13/civ13",
-  "size": {
-    "x": 32,
-    "y": 32
-  },
-  "states": [
-    {
-      "name": "",
-      "delays": [
-        [
-          0.120000005,
-          0.120000005,
-          0.120000005,
-          0.120000005
-        ]
-      ]
-    },
-    {
-      "name": "box"
-    },
-    {
-      "name": "boxnbc"
-    },
-    {
-      "name": "lighttube"
-    },
-    {
-      "name": "giftbag0"
-    },
-    {
-      "name": "giftbag1"
-    },
-    {
-      "name": "giftbag2"
-    },
-    {
-      "name": "lockbox\u002Bl"
-    },
-    {
-      "name": "lockbox"
-    },
-    {
-      "name": "lockbox\u002Bb"
-    },
-    {
-      "name": "crate"
-    },
-    {
-      "name": "crateopen"
-    },
-    {
-      "name": "securecrate"
-    },
-    {
-      "name": "securecrateopen"
-    },
-    {
-      "name": "mil_crate_closed"
-    },
-    {
-      "name": "mil_crate_opened"
-    },
-    {
-      "name": "sandbag_crate_full"
-    },
-    {
-      "name": "sandbag_crate_66"
-    },
-    {
-      "name": "sandbag_crate_50"
-    },
-    {
-      "name": "sandbag_crate_33"
-    },
-    {
-      "name": "sandbag_crate_empty"
-    },
-    {
-      "name": "mil_crate_opened-old"
-    },
-    {
-      "name": "mil_crate_closed-old"
-    },
-    {
-      "name": "wood_crate1"
-    },
-    {
-      "name": "wood_crate_opened1"
-    },
-    {
-      "name": "wood_crate_opened"
-    },
-    {
-      "name": "wood_crate"
-    },
-    {
-      "name": "wood_chest_opened"
-    },
-    {
-      "name": "wood_chest"
-    },
-    {
-      "name": "treasure_chest"
-    },
-    {
-      "name": "treasure_chest_opened"
-    },
-    {
-      "name": "largebinsopen"
-    },
-    {
-      "name": "largebinopen"
-    },
-    {
-      "name": "densecrate"
-    },
-    {
-      "name": "densecrate_open"
-    },
-    {
-      "name": "mulecrate"
-    },
-    {
-      "name": "lisacrate"
-    },
-    {
-      "name": "largemetal"
-    },
-    {
-      "name": "largemetalopen"
-    },
-    {
-      "name": "largemetalopen-old"
-    },
-    {
-      "name": "largermetal"
-    },
-    {
-      "name": "largermetal_open"
-    },
-    {
-      "name": "largermetal_open-old"
-    },
-    {
-      "name": "largermetal-old"
-    },
-    {
-      "name": "trashcart"
-    },
-    {
-      "name": "trashcartopen"
-    },
-    {
-      "name": "trashcanweld"
-    },
-    {
-      "name": "miningcar"
-    },
-    {
-      "name": "miningcaropen"
-    },
-    {
-      "name": "miningcar_light"
-    },
-    {
-      "name": "bible"
-    },
-    {
-      "name": "koran"
-    },
-    {
-      "name": "scrapbook"
-    },
-    {
-      "name": "creeper"
-    },
-    {
-      "name": "white"
-    },
-    {
-      "name": "holylight"
-    },
-    {
-      "name": "athiest"
-    },
-    {
-      "name": "tome"
-    },
-    {
-      "name": "flare_box"
-    },
-    {
-      "name": "flare_box_full"
-    },
-    {
-      "name": "flare_box_66"
-    },
-    {
-      "name": "flare_box_33"
-    },
-    {
-      "name": "flare_box_empty"
-    },
-    {
-      "name": "donk_kit"
-    },
-    {
-      "name": "kingyellow"
-    },
-    {
-      "name": "ithaqua"
-    },
-    {
-      "name": "scientology",
-      "delays": [
-        [
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1,
-          0.1
-        ]
-      ]
-    },
-    {
-      "name": "melted"
-    },
-    {
-      "name": "necronomicon"
-    },
-    {
-      "name": "talmud"
-    },
-    {
-      "name": "orthodoxbible"
-    },
-    {
-      "name": "medbriefcase"
-    },
-    {
-      "name": "combat_aid_bag_nato"
-    },
-    {
-      "name": "advfirstaid2"
-    },
-    {
-      "name": "advfirstaid2-old"
-    },
-    {
-      "name": "ifirstaid"
-    },
-    {
-      "name": "ifirstaid_adv"
-    },
-    {
-      "name": "medkit"
-    },
-    {
-      "name": "bezerk2"
-    },
-    {
-      "name": "firefirstaid2"
-    },
-    {
-      "name": "firstaid2"
-    },
-    {
-      "name": "firstaid2-old"
-    },
-    {
-      "name": "o22"
-    },
-    {
-      "name": "antitoxin2"
-    },
-    {
-      "name": "surgerykit"
-    },
-    {
-      "name": "medical_bag"
-    },
-    {
-      "name": "medical_satchel"
-    },
-    {
-      "name": "backpack_old"
-    },
-    {
-      "name": "briefcase"
-    },
-    {
-      "name": "backpack"
-    },
-    {
-      "name": "backpack1"
-    },
-    {
-      "name": "scavpack"
-    },
-    {
-      "name": "seed_collector"
-    },
-    {
-      "name": "ore_collector"
-    },
-    {
-      "name": "waterskin"
-    },
-    {
-      "name": "quiver"
-    },
-    {
-      "name": "coinpouch1"
-    },
-    {
-      "name": "coinpouch2"
-    },
-    {
-      "name": "coinpouch_tes13"
-    },
-    {
-      "name": "wallet"
-    },
-    {
-      "name": "gator_wallet"
-    },
-    {
-      "name": "lizard_wallet"
-    },
-    {
-      "name": "jappack"
-    },
-    {
-      "name": "jappack1"
-    },
-    {
-      "name": "jappack2"
-    },
-    {
-      "name": "jappack3"
-    },
-    {
-      "name": "jappack4"
-    },
-    {
-      "name": "jappack5"
-    },
-    {
-      "name": "germanpack"
-    },
-    {
-      "name": "germanpack1"
-    },
-    {
-      "name": "uspack"
-    },
-    {
-      "name": "uspack1"
-    },
-    {
-      "name": "us_buttpack"
-    },
-    {
-      "name": "sovpack"
-    },
-    {
-      "name": "duffel"
-    },
-    {
-      "name": "bduffel"
-    },
-    {
-      "name": "rucksack"
-    },
-    {
-      "name": "rucksack1"
-    },
-    {
-      "name": "smallruck"
-    },
-    {
-      "name": "heavyrucksack"
-    },
-    {
-      "name": "heavyrucksack_black"
-    },
-    {
-      "name": "civback"
-    },
-    {
-      "name": "satchel"
-    },
-    {
-      "name": "satchel_black"
-    },
-    {
-      "name": "lizard_satchel"
-    },
-    {
-      "name": "gator_satchel"
-    },
-    {
-      "name": "policesatchel"
-    },
-    {
-      "name": "replicant_backpack"
-    },
-    {
-      "name": "rd54_modern_backpack"
-    },
-    {
-      "name": "rd54_backpack"
-    },
-    {
-      "name": "backpack_rpg_tan"
-    },
-    {
-      "name": "backpack_rpg_olive"
-    },
-    {
-      "name": "piatbackpack"
-    },
-    {
-      "name": "toolbox_red"
-    },
-    {
-      "name": "toolbox_yellow"
-    },
-    {
-      "name": "toolbox_blue"
-    },
-    {
-      "name": "toolbox_crystal"
-    },
-    {
-      "name": "bet_box"
-    },
-    {
-      "name": "bet_box_blue"
-    },
-    {
-      "name": "bet_box_red"
-    },
-    {
-      "name": "bet_box_green"
-    },
-    {
-      "name": "produce_basket"
-    },
-    {
-      "name": "mailbag"
-    },
-    {
-      "name": "moneybag"
-    },
-    {
-      "name": "dumpster"
-    },
-    {
-      "name": "dumpsteropen_full"
-    },
-    {
-      "name": "dumpsteropen_halffull"
-    },
-    {
-      "name": "dumpsteropen"
-    },
-    {
-      "name": "gerkit"
-    },
-    {
-      "name": "gerkit_open"
-    },
-    {
-      "name": "shaving_kit"
-    },
-    {
-      "name": "shaving_kit_germ"
-    },
-    {
-      "name": "fruit_crate"
-    },
-    {
-      "name": "ammo_crate"
-    },
-    {
-      "name": "ammo_can"
-    },
-    {
-      "name": "footlocker"
-    },
-    {
-      "name": "footlockeropen"
-    },
-    {
-      "name": "footlocker-old"
-    },
-    {
-      "name": "footlockeropen-old"
-    },
-    {
-      "name": "sluncho"
-    },
-    {
-      "name": "slunch"
-    },
-    {
-      "name": "urn_open"
-    },
-    {
-      "name": "urn"
-    },
-    {
-      "name": "urn2_open"
-    },
-    {
-      "name": "urn2"
-    },
-    {
-      "name": "evidence"
-    },
-    {
-      "name": "evidenceobj"
-    },
-    {
-      "name": "solution_trays"
-    },
-    {
-      "name": "parachute"
-    },
-    {
-      "name": "ifak"
-    },
-    {
-      "name": "afak"
-    },
-    {
-      "name": "freezer"
-    },
-    {
-      "name": "freezeropen"
-    },
-    {
-      "name": "cardboard"
-    },
-    {
-      "name": "cardboardopen"
-    }
-  ]
+    "version": 1,
+    "license": "AGPLv3",
+    "copyright": "Taken from Civilization 13 https://github.com/civ13/civ13",
+    "size": {
+        "x": 32,
+        "y": 32
+    },
+    "states": [
+        {
+            "name": "",
+            "delays": [
+                [
+                    0.120000005,
+                    0.120000005,
+                    0.120000005,
+                    0.120000005
+                ]
+            ]
+        },
+        {
+            "name": "supplybox"
+        },
+        {
+            "name": "box"
+        },
+        {
+            "name": "boxnbc"
+        },
+        {
+            "name": "lighttube"
+        },
+        {
+            "name": "giftbag0"
+        },
+        {
+            "name": "giftbag1"
+        },
+        {
+            "name": "giftbag2"
+        },
+        {
+            "name": "lockbox\u002Bl"
+        },
+        {
+            "name": "lockbox"
+        },
+        {
+            "name": "lockbox\u002Bb"
+        },
+        {
+            "name": "crate"
+        },
+        {
+            "name": "crateopen"
+        },
+        {
+            "name": "securecrate"
+        },
+        {
+            "name": "securecrateopen"
+        },
+        {
+            "name": "mil_crate_closed"
+        },
+        {
+            "name": "mil_crate_opened"
+        },
+        {
+            "name": "sandbag_crate_full"
+        },
+        {
+            "name": "sandbag_crate_66"
+        },
+        {
+            "name": "sandbag_crate_50"
+        },
+        {
+            "name": "sandbag_crate_33"
+        },
+        {
+            "name": "sandbag_crate_empty"
+        },
+        {
+            "name": "mil_crate_opened-old"
+        },
+        {
+            "name": "mil_crate_closed-old"
+        },
+        {
+            "name": "wood_crate1"
+        },
+        {
+            "name": "wood_crate_opened1"
+        },
+        {
+            "name": "wood_crate_opened"
+        },
+        {
+            "name": "wood_crate"
+        },
+        {
+            "name": "wood_chest_opened"
+        },
+        {
+            "name": "wood_chest"
+        },
+        {
+            "name": "treasure_chest"
+        },
+        {
+            "name": "treasure_chest_opened"
+        },
+        {
+            "name": "largebinsopen"
+        },
+        {
+            "name": "largebinopen"
+        },
+        {
+            "name": "densecrate"
+        },
+        {
+            "name": "densecrate_open"
+        },
+        {
+            "name": "mulecrate"
+        },
+        {
+            "name": "lisacrate"
+        },
+        {
+            "name": "largemetal"
+        },
+        {
+            "name": "largemetalopen"
+        },
+        {
+            "name": "largemetalopen-old"
+        },
+        {
+            "name": "largermetal"
+        },
+        {
+            "name": "largermetal_open"
+        },
+        {
+            "name": "largermetal_open-old"
+        },
+        {
+            "name": "largermetal-old"
+        },
+        {
+            "name": "trashcart"
+        },
+        {
+            "name": "trashcartopen"
+        },
+        {
+            "name": "trashcanweld"
+        },
+        {
+            "name": "miningcar"
+        },
+        {
+            "name": "miningcaropen"
+        },
+        {
+            "name": "miningcar_light"
+        },
+        {
+            "name": "bible"
+        },
+        {
+            "name": "koran"
+        },
+        {
+            "name": "scrapbook"
+        },
+        {
+            "name": "creeper"
+        },
+        {
+            "name": "white"
+        },
+        {
+            "name": "holylight"
+        },
+        {
+            "name": "athiest"
+        },
+        {
+            "name": "tome"
+        },
+        {
+            "name": "flare_box"
+        },
+        {
+            "name": "flare_box_full"
+        },
+        {
+            "name": "flare_box_66"
+        },
+        {
+            "name": "flare_box_33"
+        },
+        {
+            "name": "flare_box_empty"
+        },
+        {
+            "name": "donk_kit"
+        },
+        {
+            "name": "kingyellow"
+        },
+        {
+            "name": "ithaqua"
+        },
+        {
+            "name": "scientology",
+            "delays": [
+                [
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1,
+                    0.1
+                ]
+            ]
+        },
+        {
+            "name": "melted"
+        },
+        {
+            "name": "necronomicon"
+        },
+        {
+            "name": "talmud"
+        },
+        {
+            "name": "orthodoxbible"
+        },
+        {
+            "name": "medbriefcase"
+        },
+        {
+            "name": "combat_aid_bag_nato"
+        },
+        {
+            "name": "advfirstaid2"
+        },
+        {
+            "name": "advfirstaid2-old"
+        },
+        {
+            "name": "ifirstaid"
+        },
+        {
+            "name": "ifirstaid_adv"
+        },
+        {
+            "name": "medkit"
+        },
+        {
+            "name": "bezerk2"
+        },
+        {
+            "name": "firefirstaid2"
+        },
+        {
+            "name": "firstaid2"
+        },
+        {
+            "name": "firstaid2-old"
+        },
+        {
+            "name": "o22"
+        },
+        {
+            "name": "antitoxin2"
+        },
+        {
+            "name": "surgerykit"
+        },
+        {
+            "name": "medical_bag"
+        },
+        {
+            "name": "medical_satchel"
+        },
+        {
+            "name": "backpack_old"
+        },
+        {
+            "name": "briefcase"
+        },
+        {
+            "name": "backpack"
+        },
+        {
+            "name": "backpack1"
+        },
+        {
+            "name": "scavpack"
+        },
+        {
+            "name": "seed_collector"
+        },
+        {
+            "name": "ore_collector"
+        },
+        {
+            "name": "waterskin"
+        },
+        {
+            "name": "quiver"
+        },
+        {
+            "name": "coinpouch1"
+        },
+        {
+            "name": "coinpouch2"
+        },
+        {
+            "name": "coinpouch_tes13"
+        },
+        {
+            "name": "wallet"
+        },
+        {
+            "name": "gator_wallet"
+        },
+        {
+            "name": "lizard_wallet"
+        },
+        {
+            "name": "jappack"
+        },
+        {
+            "name": "jappack1"
+        },
+        {
+            "name": "jappack2"
+        },
+        {
+            "name": "jappack3"
+        },
+        {
+            "name": "jappack4"
+        },
+        {
+            "name": "jappack5"
+        },
+        {
+            "name": "germanpack"
+        },
+        {
+            "name": "germanpack1"
+        },
+        {
+            "name": "uspack"
+        },
+        {
+            "name": "uspack1"
+        },
+        {
+            "name": "us_buttpack"
+        },
+        {
+            "name": "sovpack"
+        },
+        {
+            "name": "duffel"
+        },
+        {
+            "name": "bduffel"
+        },
+        {
+            "name": "rucksack"
+        },
+        {
+            "name": "rucksack1"
+        },
+        {
+            "name": "smallruck"
+        },
+        {
+            "name": "heavyrucksack"
+        },
+        {
+            "name": "heavyrucksack_black"
+        },
+        {
+            "name": "civback"
+        },
+        {
+            "name": "satchel"
+        },
+        {
+            "name": "satchel_black"
+        },
+        {
+            "name": "lizard_satchel"
+        },
+        {
+            "name": "gator_satchel"
+        },
+        {
+            "name": "policesatchel"
+        },
+        {
+            "name": "replicant_backpack"
+        },
+        {
+            "name": "rd54_modern_backpack"
+        },
+        {
+            "name": "rd54_backpack"
+        },
+        {
+            "name": "backpack_rpg_tan"
+        },
+        {
+            "name": "backpack_rpg_olive"
+        },
+        {
+            "name": "piatbackpack"
+        },
+        {
+            "name": "toolbox_red"
+        },
+        {
+            "name": "toolbox_yellow"
+        },
+        {
+            "name": "toolbox_blue"
+        },
+        {
+            "name": "toolbox_crystal"
+        },
+        {
+            "name": "bet_box"
+        },
+        {
+            "name": "bet_box_blue"
+        },
+        {
+            "name": "bet_box_red"
+        },
+        {
+            "name": "bet_box_green"
+        },
+        {
+            "name": "produce_basket"
+        },
+        {
+            "name": "mailbag"
+        },
+        {
+            "name": "moneybag"
+        },
+        {
+            "name": "dumpster"
+        },
+        {
+            "name": "dumpsteropen_full"
+        },
+        {
+            "name": "dumpsteropen_halffull"
+        },
+        {
+            "name": "dumpsteropen"
+        },
+        {
+            "name": "gerkit"
+        },
+        {
+            "name": "gerkit_open"
+        },
+        {
+            "name": "shaving_kit"
+        },
+        {
+            "name": "shaving_kit_germ"
+        },
+        {
+            "name": "fruit_crate"
+        },
+        {
+            "name": "ammo_crate"
+        },
+        {
+            "name": "ammo_can"
+        },
+        {
+            "name": "footlocker"
+        },
+        {
+            "name": "footlockeropen"
+        },
+        {
+            "name": "footlocker-old"
+        },
+        {
+            "name": "footlockeropen-old"
+        },
+        {
+            "name": "sluncho"
+        },
+        {
+            "name": "slunch"
+        },
+        {
+            "name": "urn_open"
+        },
+        {
+            "name": "urn"
+        },
+        {
+            "name": "urn2_open"
+        },
+        {
+            "name": "urn2"
+        },
+        {
+            "name": "evidence"
+        },
+        {
+            "name": "evidenceobj"
+        },
+        {
+            "name": "solution_trays"
+        },
+        {
+            "name": "parachute"
+        },
+        {
+            "name": "ifak"
+        },
+        {
+            "name": "afak"
+        },
+        {
+            "name": "freezer"
+        },
+        {
+            "name": "freezeropen"
+        },
+        {
+            "name": "cardboard"
+        },
+        {
+            "name": "cardboardopen"
+        }
+    ]
 }

BIN
Resources/Textures/Civ14/Objects/Storage/storage.rsi/supplybox.png


+ 4 - 0
Resources/Textures/Civ14/Structures/barricades.rsi/meta.json

@@ -15,6 +15,10 @@
             "name": "rock_barricade",
             "directions": 4
         },
+        {
+            "name": "sandbagfull",
+            "directions": 4
+        },
         {
             "name": "sandbag",
             "directions": 4

BIN
Resources/Textures/Civ14/Structures/barricades.rsi/sandbagfull.png


BIN
Resources/Textures/Civ14/Weapons/Guns/ak12.rsi/equipped-BACKPACK.png


BIN
Resources/Textures/Civ14/Weapons/Guns/ak12.rsi/mag-0.png


+ 5 - 1
Resources/Textures/Civ14/Weapons/Guns/ak12.rsi/meta.json

@@ -19,6 +19,10 @@
             "name": "icon",
             "directions": 1
         },
+        {
+            "name": "equipped-BACKPACK",
+            "directions": 4
+        },
         {
             "name": "inhand-left",
             "directions": 4
@@ -40,4 +44,4 @@
             "directions": 4
         }
     ]
-}
+}

BIN
Resources/Textures/Civ14/Weapons/Guns/ak47.rsi/mag-0.png


BIN
Resources/Textures/Civ14/Weapons/Guns/ak47_magak.rsi/ak47_magak.png


BIN
Resources/Textures/Civ14/Weapons/Guns/ak47_magak.rsi/bolt-open.png


BIN
Resources/Textures/Civ14/Weapons/Guns/ak47_magak.rsi/icon.png


+ 0 - 27
Resources/Textures/Civ14/Weapons/Guns/ak47_magak.rsi/meta.json

@@ -1,27 +0,0 @@
-{
-  "version": 1,
-  "license": "AGPL-3.0",
-  "copyright": "Exported from https://github.com/civ13/civ13",
-  "size": {
-    "x": 32,
-    "y": 32
-  },
-  "states": [
-    {
-      "name": "mag-0",
-      "directions": 1
-    },
-    {
-      "name": "ak47_magak",
-      "directions": 1
-    },
-    {
-      "name": "icon",
-      "directions": 1
-    },
-    {
-      "name": "bolt-open",
-      "directions": 1
-    }
-  ]
-}

BIN
Resources/Textures/Civ14/Weapons/Guns/ak74m.rsi/mag-0.png


BIN
Resources/Textures/Civ14/Weapons/Guns/ak74m_magak.rsi/ak74m_magak.png


BIN
Resources/Textures/Civ14/Weapons/Guns/ak74m_magak.rsi/bolt-open.png


Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно