From 5e8a4797d6c3b5fcddb2566f2d2e42475d25d832 Mon Sep 17 00:00:00 2001 From: Mustafa Alperen Seki Date: Sun, 9 Apr 2023 23:14:04 +0300 Subject: [PATCH] Engine update. --- .../ServerTraits/LobbyCommandsSS.cs | 88 +++++++++++++------ OpenRA.Mods.SS/Traits/World/SpawnSSUnit.cs | 14 +-- .../Widgets/Logic/Lobby/LobbySSLogic.cs | 56 +++++------- mod.config | 2 +- mods/ss/chrome/color-picker.yaml | 17 +++- mods/ss/chrome/ingame-infostats.yaml | 13 +++ mods/ss/rules/world.yaml | 3 +- mods/ss/scripts/cloak-invuln.lua | 16 ++-- mods/ss/scripts/respawn.lua | 20 +++-- 9 files changed, 141 insertions(+), 88 deletions(-) diff --git a/OpenRA.Mods.SS/ServerTraits/LobbyCommandsSS.cs b/OpenRA.Mods.SS/ServerTraits/LobbyCommandsSS.cs index b16d932..c72b5a2 100644 --- a/OpenRA.Mods.SS/ServerTraits/LobbyCommandsSS.cs +++ b/OpenRA.Mods.SS/ServerTraits/LobbyCommandsSS.cs @@ -48,6 +48,9 @@ public class LobbyCommandsSS : ServerTrait, IInterpretCommand, INotifyServerStar [TranslationReference] const string KickNone = "notification-kick-none"; + [TranslationReference] + const string NoKickSelf = "notification-kick-self"; + [TranslationReference] const string NoKickGameStarted = "notification-no-kick-game-started"; @@ -255,6 +258,26 @@ static void CheckAutoStart(S server) if (server.LobbyInfo.Slots.Any(sl => sl.Value.Required && server.LobbyInfo.ClientInSlot(sl.Key) == null)) return; + // Don't start without any players + if (server.LobbyInfo.Slots.All(sl => server.LobbyInfo.ClientInSlot(sl.Key) == null)) + return; + + // Does the host have the map installed? + if (server.Type != ServerType.Dedicated && server.ModData.MapCache[server.Map.Uid].Status != MapStatus.Available) + { + // Client 0 will always be the Host + // In some cases client 0 doesn't exist, so we untick all players + var host = server.LobbyInfo.Clients.FirstOrDefault(c => c.Index == 0); + if (host != null) + host.State = Session.ClientState.NotReady; + else + foreach (var client in server.LobbyInfo.Clients) + client.State = Session.ClientState.NotReady; + + server.SyncLobbyClients(); + return; + } + server.StartGame(); } } @@ -286,20 +309,25 @@ static bool StartGame(S server, Connection conn, Session.Client client, string s { if (!client.IsAdmin) { - server.SendOrderTo(conn, "Message", OnlyHostStartGame); + server.SendLocalizedMessageTo(conn, OnlyHostStartGame); + return true; + } + + if (server.LobbyInfo.Slots.Any(sl => sl.Value.Required && server.LobbyInfo.ClientInSlot(sl.Key) == null)) + { + server.SendLocalizedMessageTo(conn, NoStartUntilRequiredSlotsFull); return true; } - if (server.LobbyInfo.Slots.Any(sl => sl.Value.Required && - server.LobbyInfo.ClientInSlot(sl.Key) == null)) + if (server.LobbyInfo.Slots.All(sl => server.LobbyInfo.ClientInSlot(sl.Key) == null)) { - server.SendOrderTo(conn, "Message", NoStartUntilRequiredSlotsFull); + server.SendOrderTo(conn, "Message", NoStartWithoutPlayers); return true; } if (!server.LobbyInfo.GlobalSettings.EnableSingleplayer && server.LobbyInfo.NonBotPlayers.Count() < 2) { - server.SendOrderTo(conn, "Message", TwoHumansRequired); + server.SendLocalizedMessageTo(conn, TwoHumansRequired); return true; } @@ -492,10 +520,11 @@ static bool SlotBot(S server, Connection conn, Session.Client client, string s) }; // Pick a random color for the bot - var colorManager = server.ModData.DefaultRules.Actors[SystemActors.World].TraitInfo(); + var colorManager = server.ModData.DefaultRules.Actors[SystemActors.World].TraitInfo(); var terrainColors = server.ModData.DefaultTerrainInfo[server.Map.TileSet].RestrictedPlayerColors; var playerColors = server.LobbyInfo.Clients.Select(c => c.Color) .Concat(server.Map.Players.Players.Values.Select(p => p.Color)); + bot.Color = bot.PreferredColor = colorManager.RandomPresetColor(server.Random, terrainColors, playerColors); server.LobbyInfo.Clients.Add(bot); @@ -526,7 +555,7 @@ static bool Map(S server, Connection conn, Session.Client client, string s) } var lastMap = server.LobbyInfo.GlobalSettings.Map; - Action selectMap = map => + void SelectMap(MapPreview map) { lock (server.LobbyInfo) { @@ -612,28 +641,28 @@ static bool Map(S server, Connection conn, Session.Client client, string s) if (briefing != null) server.SendMessage(briefing); } - }; + } - Action queryFailed = () => server.SendLocalizedMessageTo(conn, UnknownMap); + void QueryFailed() => server.SendLocalizedMessageTo(conn, UnknownMap); var m = server.ModData.MapCache[s]; if (m.Status == MapStatus.Available || m.Status == MapStatus.DownloadAvailable) - selectMap(m); + SelectMap(m); else if (server.Settings.QueryMapRepository) { server.SendLocalizedMessageTo(conn, SearchingMap); var mapRepository = server.ModData.Manifest.Get().MapRepository; var reported = false; - server.ModData.MapCache.QueryRemoteMapDetails(mapRepository, new[] { s }, selectMap, _ => + server.ModData.MapCache.QueryRemoteMapDetails(mapRepository, new[] { s }, SelectMap, _ => { if (!reported) - queryFailed(); + QueryFailed(); reported = true; }); } else - queryFailed(); + QueryFailed(); return true; } @@ -750,9 +779,9 @@ static bool Kick(S server, Connection conn, Session.Client client, string s) return true; } - Exts.TryParseIntegerInvariant(split[0], out var kickClientID); + var kickConn = Exts.TryParseIntegerInvariant(split[0], out var kickClientID) + ? server.Conns.SingleOrDefault(c => server.GetClient(c)?.Index == kickClientID) : null; - var kickConn = server.Conns.SingleOrDefault(c => server.GetClient(c)?.Index == kickClientID); if (kickConn == null) { server.SendLocalizedMessageTo(conn, KickNone); @@ -760,21 +789,27 @@ static bool Kick(S server, Connection conn, Session.Client client, string s) } var kickClient = server.GetClient(kickConn); - if (server.State == ServerState.GameStarted && !kickClient.IsObserver) + if (client == kickClient) + { + server.SendLocalizedMessageTo(conn, NoKickSelf); + return true; + } + + if (!server.CanKickClient(kickClient)) { server.SendLocalizedMessageTo(conn, NoKickGameStarted); return true; } Log.Write("server", $"Kicking client {kickClientID}."); - server.SendLocalizedMessage(Kicked, Translation.Arguments("admin", client.Name, "client", kickClient.Name)); + server.SendLocalizedMessage(Kicked, Translation.Arguments("admin", client.Name, "player", kickClient.Name)); server.SendOrderTo(kickConn, "ServerError", YouWereKicked); server.DropClient(kickConn); if (bool.TryParse(split[1], out var tempBan) && tempBan) { Log.Write("server", $"Temporarily banning client {kickClientID} ({kickClient.IPAddress})."); - server.SendLocalizedMessage(TempBan, Translation.Arguments("admin", client.Name, "client", kickClient.Name)); + server.SendLocalizedMessage(TempBan, Translation.Arguments("admin", client.Name, "player", kickClient.Name)); server.TempBans.Add(kickClient.IPAddress); } @@ -795,8 +830,8 @@ static bool MakeAdmin(S server, Connection conn, Session.Client client, string s return true; } - Exts.TryParseIntegerInvariant(s, out var newAdminId); - var newAdminConn = server.Conns.SingleOrDefault(c => server.GetClient(c)?.Index == newAdminId); + var newAdminConn = Exts.TryParseIntegerInvariant(s, out var newAdminId) + ? server.Conns.SingleOrDefault(c => server.GetClient(c)?.Index == newAdminId) : null; if (newAdminConn == null) { @@ -832,8 +867,9 @@ static bool MakeSpectator(S server, Connection conn, Session.Client client, stri return true; } - Exts.TryParseIntegerInvariant(s, out var targetId); - var targetConn = server.Conns.SingleOrDefault(c => server.GetClient(c)?.Index == targetId); + var targetConn = Exts.TryParseIntegerInvariant(s, out var targetId) + ? server.Conns.SingleOrDefault(c => server.GetClient(c)?.Index == targetId) : null; + if (targetConn == null) { server.SendLocalizedMessageTo(conn, EmptySlot); @@ -1195,20 +1231,20 @@ static Color SanitizePlayerColor(S server, Color askedColor, int playerIndex, Co { lock (server.LobbyInfo) { - var colorManager = server.ModData.DefaultRules.Actors[SystemActors.World].TraitInfo(); + var colorManager = server.ModData.DefaultRules.Actors[SystemActors.World].TraitInfo(); var askColor = askedColor; - Action onError = message => + void OnError(string message) { if (connectionToEcho != null && message != null) server.SendLocalizedMessageTo(connectionToEcho, message); - }; + } var terrainColors = server.ModData.DefaultTerrainInfo[server.Map.TileSet].RestrictedPlayerColors; var playerColors = server.LobbyInfo.Clients.Where(c => c.Index != playerIndex).Select(c => c.Color) .Concat(server.Map.Players.Players.Values.Select(p => p.Color)).ToList(); - return colorManager.MakeValid(askColor, server.Random, terrainColors, playerColors, onError); + return colorManager.MakeValid(askColor, server.Random, terrainColors, playerColors, OnError); } } diff --git a/OpenRA.Mods.SS/Traits/World/SpawnSSUnit.cs b/OpenRA.Mods.SS/Traits/World/SpawnSSUnit.cs index 98450d3..a774d9d 100644 --- a/OpenRA.Mods.SS/Traits/World/SpawnSSUnit.cs +++ b/OpenRA.Mods.SS/Traits/World/SpawnSSUnit.cs @@ -98,18 +98,18 @@ public class SpawnSSUnit : IWorldLoaded readonly SpawnSSUnitInfo info; WorldRenderer wr; - HashSet<(string[] Actors, int Amount, int Inner, int Outer)> bases = new HashSet<(string[] actors, int amount, int inner, int outer)>(); + HashSet<(string[] Actors, int Amount, int Inner, int Outer)> bases = new(); public bool TeamSpawns; public bool QuickClassChange; public bool ClassChanging = true; public bool ClassChangingPaused = false; - public Dictionary PlayerSpawnPoints = new Dictionary(); - public Dictionary TeamLeaders = new Dictionary(); - public Dictionary Teams = new Dictionary(); - public Dictionary Classes = new Dictionary(); - public Dictionary Units = new Dictionary(); - Dictionary spawnPointOccupation = new Dictionary(); + public Dictionary PlayerSpawnPoints = new(); + public Dictionary TeamLeaders = new(); + public Dictionary Teams = new(); + public Dictionary Classes = new(); + public Dictionary Units = new(); + Dictionary spawnPointOccupation = new(); public SpawnSSUnit(SpawnSSUnitInfo info) { diff --git a/OpenRA.Mods.SS/Widgets/Logic/Lobby/LobbySSLogic.cs b/OpenRA.Mods.SS/Widgets/Logic/Lobby/LobbySSLogic.cs index 2beea1c..b158541 100644 --- a/OpenRA.Mods.SS/Widgets/Logic/Lobby/LobbySSLogic.cs +++ b/OpenRA.Mods.SS/Widgets/Logic/Lobby/LobbySSLogic.cs @@ -81,30 +81,28 @@ enum PanelType { Players, Options, Music, Servers, Kick, ForceStart } readonly Widget newSpectatorTemplate; readonly ScrollPanelWidget lobbyChatPanel; - readonly Dictionary chatTemplates = new Dictionary(); + readonly Dictionary chatTemplates = new(); readonly TextFieldWidget chatTextField; readonly CachedTransform chatAvailableIn; readonly string chatDisabled; readonly ScrollPanelWidget players; - readonly Dictionary factions = new Dictionary(); + readonly Dictionary factions = new(); - readonly ColorPickerManagerInfo colorManager; + readonly IColorPickerManagerInfo colorManager; - readonly TabCompletionLogic tabCompletion = new TabCompletionLogic(); + readonly TabCompletionLogic tabCompletion = new(); MapPreview map; Session.MapStatus mapStatus; - string lastUpdatedMap = null; - bool chatEnabled; bool addBotOnMapLoad; bool disableTeamChat; bool teamChat; bool updateDiscordStatus = true; - Dictionary spawnOccupants = new Dictionary(); + Dictionary spawnOccupants = new(); readonly string chatLineSound = ChromeMetrics.Get("ChatLineSound"); @@ -118,7 +116,7 @@ void ConnectionStateChanged(OrderManager om, string password, NetworkConnection // Show connection failed dialog Ui.CloseWindow(); - Action onConnect = () => + void OnConnect() { Game.OpenWindow("SERVER_LOBBY", new WidgetArgs() { @@ -126,9 +124,9 @@ void ConnectionStateChanged(OrderManager om, string password, NetworkConnection { "onStart", onStart }, { "skirmishMode", false } }); - }; + } - Action onRetry = pass => ConnectionLogic.Connect(connection.Target, pass, onConnect, onExit); + Action onRetry = pass => ConnectionLogic.Connect(connection.Target, pass, OnConnect, onExit); var switchPanel = CurrentServerSettings.ServerExternalMod != null ? "CONNECTION_SWITCHMOD_PANEL" : "CONNECTIONFAILED_PANEL"; Ui.OpenWindow(switchPanel, new WidgetArgs() @@ -137,6 +135,7 @@ void ConnectionStateChanged(OrderManager om, string password, NetworkConnection { "connection", connection }, { "password", password }, { "onAbort", onExit }, + { "onQuit", null }, { "onRetry", onRetry } }); } @@ -198,8 +197,7 @@ internal LobbySSLogic(Widget widget, ModData modData, WorldRenderer worldRendere editableSpectatorTemplate = players.Get("TEMPLATE_EDITABLE_SPECTATOR"); nonEditableSpectatorTemplate = players.Get("TEMPLATE_NONEDITABLE_SPECTATOR"); newSpectatorTemplate = players.Get("TEMPLATE_NEW_SPECTATOR"); - colorManager = modRules.Actors[SystemActors.World].TraitInfo(); - colorManager.Color = Game.Settings.Player.Color; + colorManager = modRules.Actors[SystemActors.World].TraitInfo(); foreach (var f in modRules.Actors[SystemActors.World].TraitInfos()) factions.Add(f.InternalName, new LobbyFaction { Selectable = f.Selectable, Name = f.Name, Side = f.Side, Description = f.Description }); @@ -233,9 +231,9 @@ internal LobbySSLogic(Widget widget, ModData modData, WorldRenderer worldRendere Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs() { - { "initialMap", SelectRecentMap(map.Uid) }, + { "initialMap", modData.MapCache.PickLastModifiedMap(MapVisibility.Lobby) ?? map.Uid }, { "initialTab", MapClassification.System }, - { "onExit", Game.IsHost ? (Action)UpdateSelectedMap : modData.MapCache.UpdateMaps }, + { "onExit", Game.IsHost ? UpdateSelectedMap : modData.MapCache.UpdateMaps }, { "onSelect", Game.IsHost ? onSelect : null }, { "filter", MapVisibility.Lobby }, }); @@ -270,7 +268,7 @@ internal LobbySSLogic(Widget widget, ModData modData, WorldRenderer worldRendere { var bot = botTypes.Random(Game.CosmeticRandom); var c = orderManager.LobbyInfo.ClientInSlot(slot.Key); - if (slot.Value.AllowBots == true && (c == null || c.Bot != null)) + if (slot.Value.AllowBots && (c == null || c.Bot != null)) orderManager.IssueOrder(Order.Command($"slot_bot {slot.Key} {botController.Index} {bot}")); } } @@ -328,13 +326,14 @@ internal LobbySSLogic(Widget widget, ModData modData, WorldRenderer worldRendere options.Add(modData.Translation.GetString(ConfigureTeams), teamOptions); } - Func setupItem = (option, template) => + ScrollItemWidget SetupItem(DropDownOptionSS option, ScrollItemWidget template) { var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick); item.Get("LABEL").GetText = () => option.Title; return item; - }; - slotsButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 175, options, setupItem); + } + + slotsButton.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 175, options, SetupItem); }; } @@ -402,7 +401,7 @@ internal LobbySSLogic(Widget widget, ModData modData, WorldRenderer worldRendere } // Force start panel - Action startGame = () => + void StartGame() { // Refresh MapCache and check if the selected map is available before attempting to start the game if (modData.MapCache[map.Uid].Status == MapStatus.Available) @@ -412,7 +411,7 @@ internal LobbySSLogic(Widget widget, ModData modData, WorldRenderer worldRendere } else UpdateSelectedMap(); - }; + } var startGameButton = lobby.GetOrNull("START_GAME_BUTTON"); if (startGameButton != null) @@ -428,14 +427,14 @@ internal LobbySSLogic(Widget widget, ModData modData, WorldRenderer worldRendere if (orderManager.LobbyInfo.Clients.Any(c => c.Slot != null && !c.IsAdmin && c.Bot == null && !c.IsReady)) panel = PanelType.ForceStart; else - startGame(); + StartGame(); }; } var forceStartBin = Ui.LoadWidget("FORCE_START_DIALOG", lobby.Get("TOP_PANELS_ROOT"), new WidgetArgs()); forceStartBin.IsVisible = () => panel == PanelType.ForceStart; forceStartBin.Get("KICK_WARNING").IsVisible = () => orderManager.LobbyInfo.Clients.Any(c => c.IsInvalid); - forceStartBin.Get("OK_BUTTON").OnClick = startGame; + forceStartBin.Get("OK_BUTTON").OnClick = StartGame; forceStartBin.Get("CANCEL_BUTTON").OnClick = () => panel = PanelType.Players; var disconnectButton = lobby.Get("DISCONNECT_BUTTON"); @@ -548,7 +547,7 @@ public override void Tick() panel = PanelType.Players; var chatWasEnabled = chatEnabled; - chatEnabled = Game.RunTime >= TextNotificationsManager.ChatDisabledUntil && TextNotificationsManager.ChatDisabledUntil != uint.MaxValue; + chatEnabled = worldRenderer.World.IsReplay || (Game.RunTime >= TextNotificationsManager.ChatDisabledUntil && TextNotificationsManager.ChatDisabledUntil != uint.MaxValue); if (chatEnabled && !chatWasEnabled) { @@ -882,17 +881,6 @@ void UpdateSelectedMap() Game.Settings.Save(); } } - - string SelectRecentMap(string currentUid) - { - if (lastUpdatedMap != modData.MapCache.LastModifiedMap) - { - lastUpdatedMap = modData.MapCache.LastModifiedMap; - return lastUpdatedMap; - } - - return currentUid; - } } class DropDownOptionSS diff --git a/mod.config b/mod.config index 8f3d81e..e4e56ff 100644 --- a/mod.config +++ b/mod.config @@ -9,7 +9,7 @@ MOD_ID="ss" # The OpenRA engine version to use for this project. -ENGINE_VERSION="e64c0a3" +ENGINE_VERSION="3ca2bb1" ############################################################################## # Packaging diff --git a/mods/ss/chrome/color-picker.yaml b/mods/ss/chrome/color-picker.yaml index d3291ca..16f51e9 100644 --- a/mods/ss/chrome/color-picker.yaml +++ b/mods/ss/chrome/color-picker.yaml @@ -47,12 +47,25 @@ Background@COLOR_CHOOSER: Width: PARENT_RIGHT - 91 Height: PARENT_BOTTOM - 34 Children: - Background@MIXERBG: + Background@HUEBG: Background: panel-black X: 0 Y: 0 Width: PARENT_RIGHT - Height: 114 + Height: 17 + Children: + HueSlider@HUE_SLIDER: + X: 2 + Y: 2 + Width: PARENT_RIGHT - 4 + Height: PARENT_BOTTOM - 4 + Ticks: 5 + Background@MIXERBG: + Background: panel-black + X: 0 + Y: 21 + Width: PARENT_RIGHT + Height: PARENT_BOTTOM - 21 Children: ColorMixer@MIXER: X: 2 diff --git a/mods/ss/chrome/ingame-infostats.yaml b/mods/ss/chrome/ingame-infostats.yaml index ec1db09..87db207 100644 --- a/mods/ss/chrome/ingame-infostats.yaml +++ b/mods/ss/chrome/ingame-infostats.yaml @@ -136,6 +136,19 @@ Container@SKIRMISH_STATS: Checkmark: mute Background: checkbox-toggle TooltipContainer: TOOLTIP_CONTAINER + Button@KICK: + X: 485 + Width: 25 + Height: 25 + Background: checkbox-toggle + TooltipContainer: TOOLTIP_CONTAINER + TooltipText: Kick this player + Children: + Image: + ImageCollection: lobby-bits + ImageName: kick + X: 7 + Y: 7 Container@SPECTATOR_TEMPLATE: Width: PARENT_RIGHT - 27 Height: 25 diff --git a/mods/ss/rules/world.yaml b/mods/ss/rules/world.yaml index d1122c8..a00d4c3 100644 --- a/mods/ss/rules/world.yaml +++ b/mods/ss/rules/world.yaml @@ -635,8 +635,7 @@ World: CellTriggerOverlay: ColorPickerManager: PreviewActor: fact.colorpicker - PresetHues: 0, 0.055, 0.11, 0.165, 0.22, 0.275, 0.33, 0.385, 0.44, 0, 0.055, 0.11, 0.165, 0.22, 0.275, 0.33, 0.385, 0.44, 0, 0.055, 0.11, 0.165, 0.22, 0.275, 0.33, 0.385, 0.44, 0.495, 0.55, 0.605, 0.66, 0.715, 0.77, 0.825, 0.88, 0.935, 0.495, 0.55, 0.605, 0.66, 0.715, 0.77, 0.825, 0.88, 0.935, 0.495, 0.55, 0.605, 0.66, 0.715, 0.77, 0.825, 0.88, 0.935 - PresetSaturations: 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 + PresetColors: C4BA91, 94BBE3, ED7777, 62C462, FCC27E, 688F85, FF9EE0, D0FF80, DDE0BA, C4B060, 4494E4, EC0000, 00C400, FC8800, 44907C, FF40C4, A0FF00, DAE096, 625830, 224A72, 760000, 006200, 7E4400, 22483E, 802061, 518000, 6D704B, FFEE80, 7070E0, EDCECE, 608060, 704E4A, 70E0E0, B466CC, E0A890, BAE0CF, FFDD00, 0000E0, EEB2B2, 408040, 702C24, 00E0E0, 9C00CC, E07040, 96E0BD, 806E00, 000070, 775959, 204020, 381612, 007070, 4E0066, 703821, 4B705E FactionPreviewActors: Infantry: e1.colorpicker Vehicle: harv.colorpicker diff --git a/mods/ss/scripts/cloak-invuln.lua b/mods/ss/scripts/cloak-invuln.lua index 0cfbea1..c0fccbb 100644 --- a/mods/ss/scripts/cloak-invuln.lua +++ b/mods/ss/scripts/cloak-invuln.lua @@ -40,12 +40,14 @@ end CloakInvulnWorldLoaded = function() players = Player.GetPlayers(function(p) return not p.IsNonCombatant end) - for _,player in pairs(players) do - if StartingCloakOption ~= "disabled" then - player.Unit.GrantCondition("starting-cloak", CloakDuration[StartingCloakOption]) + Trigger.AfterDelay(0, function() + for _,player in pairs(players) do + if StartingCloakOption ~= "disabled" then + player.Unit.GrantCondition("starting-cloak", CloakDuration[StartingCloakOption]) + end + if StartingInvulnOption ~= "disabled" then + player.Unit.GrantCondition("invulnerability", InvulnDuration[StartingInvulnOption]) + end end - if StartingInvulnOption ~= "disabled" then - player.Unit.GrantCondition("invulnerability", InvulnDuration[StartingInvulnOption]) - end - end + end) end diff --git a/mods/ss/scripts/respawn.lua b/mods/ss/scripts/respawn.lua index 650099c..3216744 100644 --- a/mods/ss/scripts/respawn.lua +++ b/mods/ss/scripts/respawn.lua @@ -235,15 +235,17 @@ RespawnWorldLoaded = function() ReshroudOnDeath = neutral.HasPrerequisites({ "global-reshroudondeath" }) SetupObjectives() - for _,player in pairs(players) do - if RespawnOption ~= "disabled" then - Respawn(player) + Trigger.AfterDelay(0, function() + for _,player in pairs(players) do + if RespawnOption ~= "disabled" then + Respawn(player) - SpawnPoints[player.InternalName] = player.SpawnCellPosition - else - Trigger.OnKilled(player.Unit, function() - player.MarkFailedObjective(0) - end) + SpawnPoints[player.InternalName] = player.SpawnCellPosition + else + Trigger.OnKilled(player.Unit, function() + player.MarkFailedObjective(0) + end) + end end - end + end) end