From c7545d5816cdaacf8374b36bdf95cd3f6476d11c Mon Sep 17 00:00:00 2001 From: Regalis Date: Wed, 6 Apr 2016 18:36:26 +0300 Subject: [PATCH] - StartCoroutine returns a handle which can be used to stop a coroutine, and coroutines and be given a name to make accessing them easier - StatusEffect coroutines are stopped when the round ends - Fixed GameServer keeping a reference to the TraitorManager after a round ends (causing traitor messages to appear even if traitors aren't on anymore) - Option to spawn characters near/inside/outside the sub using the spawn command --- Subsurface/Source/Characters/StatusEffect.cs | 15 ++-- Subsurface/Source/CoroutineManager.cs | 71 ++++++++++++------- Subsurface/Source/DebugConsole.cs | 57 +++++++++++++-- .../GameModes/Tutorials/TutorialType.cs | 4 +- Subsurface/Source/GameSession/GameSession.cs | 3 +- Subsurface/Source/Networking/GameServer.cs | 7 +- 6 files changed, 114 insertions(+), 43 deletions(-) diff --git a/Subsurface/Source/Characters/StatusEffect.cs b/Subsurface/Source/Characters/StatusEffect.cs index 3796de97a..0cc621309 100644 --- a/Subsurface/Source/Characters/StatusEffect.cs +++ b/Subsurface/Source/Characters/StatusEffect.cs @@ -13,7 +13,7 @@ namespace Barotrauma { This = 1, Parent = 2, Character = 4, Contained = 8, Nearby = 16, UseTarget = 32, Hull = 64 } - + private TargetType targetTypes; private string[] targetNames; @@ -246,13 +246,13 @@ namespace Barotrauma { ObjectProperty property; - //if (targetNames!=null && !targetNames.Contains(target.Name)) continue; - if (!target.ObjectProperties.TryGetValue(propertyNames[i], out property)) continue; if (duration > 0.0f) { - CoroutineManager.StartCoroutine(ApplyToPropertyOverDuration(duration, property, propertyEffects[i])); + CoroutineManager.StartCoroutine( + ApplyToPropertyOverDuration(duration, property, propertyEffects[i]), "statuseffect"); + } else { @@ -318,6 +318,11 @@ namespace Barotrauma { DelayedEffect.List[i].Update(deltaTime); } - } + } + + public static void StopAll() + { + CoroutineManager.StopCoroutines("statuseffect"); + } } } diff --git a/Subsurface/Source/CoroutineManager.cs b/Subsurface/Source/CoroutineManager.cs index dd2847a00..7d9617d9b 100644 --- a/Subsurface/Source/CoroutineManager.cs +++ b/Subsurface/Source/CoroutineManager.cs @@ -9,34 +9,52 @@ namespace Barotrauma Running, Success, Failure } + class CoroutineHandle + { + public readonly IEnumerator Coroutine; + public readonly string Name; + + public CoroutineHandle(IEnumerator coroutine, string name = "") + { + Coroutine = coroutine; + Name = string.IsNullOrWhiteSpace(name) ? coroutine.ToString() : name; + } + + } + // Keeps track of all running coroutines, and runs them till the end. static class CoroutineManager { - static readonly List> Coroutines = new List>(); + static readonly List Coroutines = new List(); public static float UnscaledDeltaTime, DeltaTime; - // Starting a coroutine just means adding an enumerator to the list. - // You might also want to be able to stop coroutines or delete them, - // which might mean putting them into a dictionary - public static void StartCoroutine(IEnumerable func) + public static CoroutineHandle StartCoroutine(IEnumerable func, string name = "") { - Coroutines.Add(func.GetEnumerator()); + var handle = new CoroutineHandle(func.GetEnumerator(), name); + Coroutines.Add(handle); + + return handle; } public static bool IsCoroutineRunning(string name) { - IEnumerator coroutine = Coroutines.FirstOrDefault( - c => c.ToString().Contains(name)); + return Coroutines.Any(c => c.Name == name); + } - return coroutine!=null; + public static bool IsCoroutineRunning(CoroutineHandle handle) + { + return Coroutines.Contains(handle); } - public static void StopCoroutine(string name) + public static void StopCoroutines(string name) { - IEnumerator coroutine = Coroutines.FirstOrDefault(c => c.ToString().Contains(name)); + Coroutines.RemoveAll(c => c.Name == name); + } - if (coroutine != null) Coroutines.Remove(coroutine); + public static void StopCoroutines(CoroutineHandle handle) + { + Coroutines.RemoveAll(c => c == handle); } // Updating just means stepping through all the coroutines @@ -47,16 +65,16 @@ namespace Barotrauma for (int i = Coroutines.Count-1; i>=0; i--) { - if (Coroutines[i].Current != null) + if (Coroutines[i].Coroutine.Current != null) { - WaitForSeconds wfs = Coroutines[i].Current as WaitForSeconds; + WaitForSeconds wfs = Coroutines[i].Coroutine.Current as WaitForSeconds; if (wfs != null) { if (!wfs.CheckFinished(unscaledDeltaTime)) continue; } else { - switch ((CoroutineStatus)Coroutines[i].Current) + switch ((CoroutineStatus)Coroutines[i].Coroutine.Current) { case CoroutineStatus.Success: Coroutines.RemoveAt(i); @@ -68,18 +86,18 @@ namespace Barotrauma } } - try - { - Coroutines[i].MoveNext(); - } + //try + //{ + Coroutines[i].Coroutine.MoveNext(); +// } - catch (Exception e) - { -#if DEBUG - DebugConsole.ThrowError("Coroutine " + Coroutines[i] + " threw an exception: " + e.Message); -#endif - Coroutines.RemoveAt(i); - } +// catch (Exception e) +// { +//#if DEBUG +// DebugConsole.ThrowError("Coroutine " + Coroutines[i] + " threw an exception: " + e.Message); +//#endif +// Coroutines.RemoveAt(i); +// } } } @@ -89,7 +107,6 @@ namespace Barotrauma { float timer; - public WaitForSeconds(float time) { timer = time; diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index ada88dab6..9060e0479 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -156,8 +156,7 @@ namespace Barotrauma NewMessage(" ", Color.Cyan); - NewMessage("spawn: spawn a creature at a random spawnpoint", Color.Cyan); - NewMessage("spawn: spawn a creature at a random spawnpoint", Color.Cyan); + NewMessage("spawn [creaturename] [near/inside/outside]: spawn a creature at a random spawnpoint (use the second parameter to only select spawnpoints near/inside/outside the submarine)", Color.Cyan); NewMessage(" ", Color.Cyan); @@ -174,6 +173,7 @@ namespace Barotrauma NewMessage(" ", Color.Cyan); NewMessage("heal: restore the controlled character to full health", Color.Cyan); + NewMessage("revive: bring the controlled character back from the dead", Color.Cyan); NewMessage(" ", Color.Cyan); @@ -196,10 +196,56 @@ namespace Barotrauma Character spawnedCharacter = null; + Vector2 spawnPosition = Vector2.Zero; + WayPoint spawnPoint = null; + + if (commands.Length > 2) + { + switch (commands[2].ToLower()) + { + case "inside": + spawnPoint = WayPoint.GetRandom(SpawnType.Human); + break; + case "outside": + spawnPoint = WayPoint.GetRandom(SpawnType.Enemy); + break; + case "near": + case "close": + if (Submarine.Loaded == null) break; + + float closestDist = 0.0f; + foreach (WayPoint wp in WayPoint.WayPointList) + { + if (wp.Submarine != null) continue; + + //don't spawn inside hulls + if (Hull.FindHull(wp.WorldPosition, null) != null) continue; + + float dist = Vector2.Distance(wp.WorldPosition, Submarine.Loaded.WorldPosition); + + if (spawnPoint == null || dist < closestDist) + { + spawnPoint = wp; + closestDist = dist; + } + } + break; + default: + spawnPoint = WayPoint.GetRandom(commands[1].ToLower()=="human" ? SpawnType.Human : SpawnType.Enemy); + break; + } + + } + else + { + spawnPoint = WayPoint.GetRandom(commands[1].ToLower() == "human" ? SpawnType.Human : SpawnType.Enemy); + } + + spawnPosition = spawnPoint == null ? Vector2.Zero : spawnPoint.WorldPosition; + if (commands[1].ToLower()=="human") { - WayPoint spawnPoint = WayPoint.GetRandom(SpawnType.Human); - spawnedCharacter = Character.Create(Character.HumanConfigFile, (spawnPoint == null) ? Vector2.Zero : spawnPoint.WorldPosition); + spawnedCharacter = Character.Create(Character.HumanConfigFile, spawnPosition); Character.Controlled = spawnedCharacter; if (GameMain.GameSession != null) @@ -212,8 +258,7 @@ namespace Barotrauma } else { - WayPoint spawnPoint = WayPoint.GetRandom(SpawnType.Enemy); - spawnedCharacter = Character.Create("Content/Characters/" + commands[1] + "/" + commands[1] + ".xml", (spawnPoint == null) ? Vector2.Zero : spawnPoint.WorldPosition); + spawnedCharacter = Character.Create("Content/Characters/" + commands[1] + "/" + commands[1] + ".xml", spawnPosition); } if (spawnedCharacter != null && GameMain.Server != null) GameMain.Server.SendCharacterSpawnMessage(spawnedCharacter); diff --git a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs index 8ccf26db4..50d06c99f 100644 --- a/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs +++ b/Subsurface/Source/GameSession/GameModes/Tutorials/TutorialType.cs @@ -76,14 +76,14 @@ namespace Barotrauma.Tutorials { if (Character.Controlled==null) { - CoroutineManager.StopCoroutine("TutorialMode.UpdateState"); + CoroutineManager.StopCoroutines("TutorialMode.UpdateState"); infoBox = null; } else if (Character.Controlled.IsDead) { Character.Controlled = null; - CoroutineManager.StopCoroutine("TutorialMode.UpdateState"); + CoroutineManager.StopCoroutines("TutorialMode.UpdateState"); infoBox = null; CoroutineManager.StartCoroutine(Dead()); } diff --git a/Subsurface/Source/GameSession/GameSession.cs b/Subsurface/Source/GameSession/GameSession.cs index 6d2813205..6ee8a7c95 100644 --- a/Subsurface/Source/GameSession/GameSession.cs +++ b/Subsurface/Source/GameSession/GameSession.cs @@ -163,9 +163,8 @@ namespace Barotrauma TaskManager.EndShift(); currentMission = null; - //gameMode.End(); - //return true; + StatusEffect.StopAll(); } diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index 06edbafe7..226304c23 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -934,10 +934,15 @@ namespace Barotrauma.Networking UpdateCrewFrame(); - if (TraitorsEnabled == YesNoMaybe.Yes || (TraitorsEnabled == YesNoMaybe.Maybe && Rand.Range(0.0f, 1.0f) < 0.5f)) + if (TraitorsEnabled == YesNoMaybe.Yes || + (TraitorsEnabled == YesNoMaybe.Maybe && Rand.Range(0.0f, 1.0f) < 0.5f)) { TraitorManager = new TraitorManager(this); } + else + { + TraitorManager = null; + } //give some time for the clients to load the map yield return new WaitForSeconds(2.0f);