diff --git a/Subsurface/Content/Characters/Crawler/attack.ogg b/Subsurface/Content/Characters/Crawler/attack.ogg deleted file mode 100644 index a4f41d094..000000000 Binary files a/Subsurface/Content/Characters/Crawler/attack.ogg and /dev/null differ diff --git a/Subsurface/Content/Characters/Crawler/attack1.ogg b/Subsurface/Content/Characters/Crawler/attack1.ogg new file mode 100644 index 000000000..8e8c6a59c Binary files /dev/null and b/Subsurface/Content/Characters/Crawler/attack1.ogg differ diff --git a/Subsurface/Content/Characters/Crawler/attack2.ogg b/Subsurface/Content/Characters/Crawler/attack2.ogg new file mode 100644 index 000000000..e1e71814c Binary files /dev/null and b/Subsurface/Content/Characters/Crawler/attack2.ogg differ diff --git a/Subsurface/Content/Characters/Crawler/crawler.xml b/Subsurface/Content/Characters/Crawler/crawler.xml index aa2176b27..4c07bf290 100644 --- a/Subsurface/Content/Characters/Crawler/crawler.xml +++ b/Subsurface/Content/Characters/Crawler/crawler.xml @@ -1,7 +1,10 @@  + + - + + 0.0f) @@ -201,7 +210,7 @@ namespace Subsurface //System.Diagnostics.Debug.WriteLine("cooldown"); - if (selectedTarget.Entity is Hull || + if (selectedAiTarget.Entity is Hull || Vector2.Distance(attackPosition, Character.AnimController.limbs[0].SimPosition) < ConvertUnits.ToSimUnits(500.0f)) { steeringManager.SteeringSeek(attackPosition, -0.8f); @@ -219,7 +228,7 @@ namespace Subsurface targetEntity = null; //check if there's a wall between the target and the character Vector2 rayStart = Character.AnimController.limbs[0].SimPosition; - Vector2 rayEnd = selectedTarget.Position; + Vector2 rayEnd = selectedAiTarget.Position; Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd); if (Submarine.LastPickedFraction == 1.0f || closestBody == null) @@ -272,7 +281,7 @@ namespace Subsurface } else { - damageTarget = selectedTarget.Entity as IDamageable; + damageTarget = selectedAiTarget.Entity as IDamageable; } attackTimer += deltaTime*0.05f; @@ -323,14 +332,14 @@ namespace Subsurface { if (distanceAccumulator<5.0f && Rand.Range(1,3, false)==1) { - selectedTarget = null; + selectedAiTarget = null; character.AnimController.TargetMovement = -character.AnimController.TargetMovement; state = AiState.None; return; } distanceAccumulator = 0.0f; - selectedTarget = null; + selectedAiTarget = null; selectedTargetMemory = null; targetValue = 0.0f; @@ -409,13 +418,13 @@ namespace Subsurface //float newTargetValue = valueModifier/dist; - if (selectedTarget == null || Math.Abs(valueModifier) > Math.Abs(targetValue)) + if (selectedAiTarget == null || Math.Abs(valueModifier) > Math.Abs(targetValue)) { - selectedTarget = target; + selectedAiTarget = target; selectedTargetMemory = targetMemory; targetValue = valueModifier; - Debug.WriteLine(selectedTarget.Entity+": "+targetValue); + Debug.WriteLine(selectedAiTarget.Entity+": "+targetValue); } } } diff --git a/Subsurface/Source/Characters/Character.cs b/Subsurface/Source/Characters/Character.cs index 8ac3aa90c..3d9009f48 100644 --- a/Subsurface/Source/Characters/Character.cs +++ b/Subsurface/Source/Characters/Character.cs @@ -123,6 +123,11 @@ namespace Subsurface get { return cursorPosition; } } + public AITarget AiTarget + { + get { return aiTarget; } + } + public float SoundRange { get { return aiTarget.SoundRange; } @@ -264,6 +269,11 @@ namespace Subsurface get { return secondaryKeyDown; } } + public AIController AIController + { + get { return aiController; } + } + public bool IsDead { get { return isDead; } diff --git a/Subsurface/Source/CoroutineManager.cs b/Subsurface/Source/CoroutineManager.cs index d34f5d6e4..ec47072c0 100644 --- a/Subsurface/Source/CoroutineManager.cs +++ b/Subsurface/Source/CoroutineManager.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -13,33 +14,71 @@ namespace Subsurface // Keeps track of all running coroutines, and runs them till the end. static class CoroutineManager { - static List> Coroutines = new List>(); + static List> Coroutines = new List>(); // 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 void StartCoroutine(IEnumerable func) { Coroutines.Add(func.GetEnumerator()); } // Updating just means stepping through all the coroutines - public static void Update() + public static void Update(float deltaTime) { for (int i = Coroutines.Count-1; i>=0; i--) { + if (Coroutines[i].Current != null) + { + if (Coroutines[i].Current is WaitForSeconds) + { + WaitForSeconds wfs = (WaitForSeconds)Coroutines[i].Current; + if (!wfs.CheckFinished(deltaTime)) continue; + + } + else + { + switch ((Status)Coroutines[i].Current) + { + case Status.Success: + Coroutines.RemoveAt(i); + continue; + case Status.Failure: + DebugConsole.ThrowError("Coroutine ''" + Coroutines[i]+ "'' has failed"); + break; + } + } + + } + + Coroutines[i].MoveNext(); - switch (Coroutines[i].Current) - { - case Status.Success: - Coroutines.RemoveAt(i); - break; - case Status.Failure: - DebugConsole.ThrowError("Coroutine ''" + Coroutines[i]+ "'' has failed"); - break; - } + } } - } + } + + class WaitForSeconds + { + float timer; + + + public WaitForSeconds(float time) + { + timer = time; + } + + public bool CheckFinished(float deltaTime) + { + timer -= deltaTime; + return timer<=0.0f; + + } + + + } + + } diff --git a/Subsurface/Source/GUI/GUI.cs b/Subsurface/Source/GUI/GUI.cs index d2c70d207..51f20f963 100644 --- a/Subsurface/Source/GUI/GUI.cs +++ b/Subsurface/Source/GUI/GUI.cs @@ -311,9 +311,9 @@ namespace Subsurface DrawMessages(spriteBatch, (float)deltaTime); - if (GUIMessageBox.messageBoxes.Count>0) + if (GUIMessageBox.MessageBoxes.Count>0) { - var messageBox = GUIMessageBox.messageBoxes.Peek(); + var messageBox = GUIMessageBox.MessageBoxes.Peek(); if (messageBox != null) messageBox.Draw(spriteBatch); } @@ -331,9 +331,9 @@ namespace Subsurface public static void Update(float deltaTime) { - if (GUIMessageBox.messageBoxes.Count > 0) + if (GUIMessageBox.MessageBoxes.Count > 0) { - var messageBox = GUIMessageBox.messageBoxes.Peek(); + var messageBox = GUIMessageBox.MessageBoxes.Peek(); if (messageBox != null) { GUIComponent.MouseOn = messageBox; diff --git a/Subsurface/Source/GUI/GUIComponent.cs b/Subsurface/Source/GUI/GUIComponent.cs index 82f2b0fbf..9eb4f70fb 100644 --- a/Subsurface/Source/GUI/GUIComponent.cs +++ b/Subsurface/Source/GUI/GUIComponent.cs @@ -38,6 +38,7 @@ namespace Subsurface protected ComponentState state; + protected Color flashColor; protected float flashTimer; public virtual SpriteFont Font @@ -204,9 +205,10 @@ namespace Subsurface return false; } - public void Flash() + public void Flash(Color? color = null) { flashTimer = FlashDuration; + flashColor = (color == null) ? Color.Red * 0.8f : (Color)color; foreach (GUIComponent child in children) { @@ -222,10 +224,9 @@ namespace Subsurface if (flashTimer>0.0f) { - Color flashColor = Color.Red * (flashTimer / FlashDuration)*0.8f; - GUI.DrawRectangle(spriteBatch, - new Rectangle(rect.X-5,rect.Y-5,rect.Width+10,rect.Height+10), flashColor, true); + new Rectangle(rect.X-5,rect.Y-5,rect.Width+10,rect.Height+10), + flashColor * (flashTimer / FlashDuration), true); } GUI.DrawRectangle(spriteBatch, rect, currColor * (currColor.A / 255.0f), true); diff --git a/Subsurface/Source/GUI/GUIListBox.cs b/Subsurface/Source/GUI/GUIListBox.cs index 39af7f1a2..b8074a1c9 100644 --- a/Subsurface/Source/GUI/GUIListBox.cs +++ b/Subsurface/Source/GUI/GUIListBox.cs @@ -121,6 +121,8 @@ namespace Subsurface UpdateScrollBarSize(); + children.Clear(); + enabled = true; scrollBarEnabled = true; diff --git a/Subsurface/Source/GUI/GUIMessageBox.cs b/Subsurface/Source/GUI/GUIMessageBox.cs index 418f04973..f5cfccb00 100644 --- a/Subsurface/Source/GUI/GUIMessageBox.cs +++ b/Subsurface/Source/GUI/GUIMessageBox.cs @@ -5,7 +5,7 @@ namespace Subsurface { class GUIMessageBox : GUIFrame { - public static Queue messageBoxes = new Queue(); + public static Queue MessageBoxes = new Queue(); const int DefaultWidth=400, DefaultHeight=200; @@ -51,14 +51,14 @@ namespace Subsurface x += this.Buttons[i].Rect.Width + 20; } - messageBoxes.Enqueue(this); + MessageBoxes.Enqueue(this); } public bool Close(GUIButton button, object obj) { if (parent != null) parent.RemoveChild(this); - messageBoxes.Dequeue(); + MessageBoxes.Dequeue(); return true; } } diff --git a/Subsurface/Source/Game1.cs b/Subsurface/Source/Game1.cs index 5c009c59b..91d528f0d 100644 --- a/Subsurface/Source/Game1.cs +++ b/Subsurface/Source/Game1.cs @@ -161,7 +161,7 @@ namespace Subsurface } private float loadState = 0.0f; - private IEnumerable Load() + private IEnumerable Load() { GUI.Font = ToolBox.TryLoadFont("SpriteFont1", Content); GUI.SmallFont = ToolBox.TryLoadFont("SmallFont", Content); @@ -199,7 +199,7 @@ namespace Subsurface loadState = 70.0f; yield return Status.Running; - GameMode.Init(); + GameModePreset.Init(); Submarine.Preload("Content/SavedMaps"); loadState = 80.0f; @@ -277,7 +277,7 @@ namespace Subsurface } } - CoroutineManager.Update(); + CoroutineManager.Update((float)deltaTime); } diff --git a/Subsurface/Source/GameSession/GameModes/GameMode.cs b/Subsurface/Source/GameSession/GameModes/GameMode.cs index af887f5b8..75c5df73a 100644 --- a/Subsurface/Source/GameSession/GameModes/GameMode.cs +++ b/Subsurface/Source/GameSession/GameModes/GameMode.cs @@ -111,25 +111,6 @@ namespace Subsurface Game1.GameSession.EndShift(endMessage); } - public static void Init() - { - new GameModePreset("Single Player", typeof(SinglePlayerMode), true); - - var mode = new GameModePreset("SandBox", typeof(GameMode), false); - mode.Description = "A game mode with no specific objectives."; - - mode = new GameModePreset("Traitor", typeof(TraitorMode), false); - mode.Description = "One of the players is selected as a traitor and given a secret objective. " - + "The rest of the crew will win if they reach the end of the level or kill the traitor " - + "before the objective is completed."; - - mode = new GameModePreset("Quest", typeof(QuestMode), false); - mode.Description = "The crew must work together to complete a specific task, such as retrieving " - + "an alien artifact or killing a creature that's terrorizing nearby outposts. The game ends " - + "when the task is completed or everyone in the crew has died."; - - - } } } diff --git a/Subsurface/Source/GameSession/GameModes/GameModePreset.cs b/Subsurface/Source/GameSession/GameModes/GameModePreset.cs index fbd6964a2..a00a22270 100644 --- a/Subsurface/Source/GameSession/GameModes/GameModePreset.cs +++ b/Subsurface/Source/GameSession/GameModes/GameModePreset.cs @@ -34,5 +34,24 @@ namespace Subsurface object[] lobject = new object[] { this }; return (GameMode)Constructor.Invoke(lobject); } + + public static void Init() + { + new GameModePreset("Single Player", typeof(SinglePlayerMode), true); + new GameModePreset("Tutorial", typeof(TutorialMode), true); + + var mode = new GameModePreset("SandBox", typeof(GameMode), false); + mode.Description = "A game mode with no specific objectives."; + + mode = new GameModePreset("Traitor", typeof(TraitorMode), false); + mode.Description = "One of the players is selected as a traitor and given a secret objective. " + + "The rest of the crew will win if they reach the end of the level or kill the traitor " + + "before the objective is completed."; + + mode = new GameModePreset("Quest", typeof(QuestMode), false); + mode.Description = "The crew must work together to complete a specific task, such as retrieving " + + "an alien artifact or killing a creature that's terrorizing nearby outposts. The game ends " + + "when the task is completed or everyone in the crew has died."; + } } } diff --git a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs index 5a14bd865..7a83faa6f 100644 --- a/Subsurface/Source/GameSession/GameModes/TutorialMode.cs +++ b/Subsurface/Source/GameSession/GameModes/TutorialMode.cs @@ -1,11 +1,342 @@ -using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Subsurface.Items.Components; +using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Subsurface { - //class TutorialMode : GameMode - //{ - //} + class TutorialMode : GameMode + { + public readonly CrewManager CrewManager; + + private GUIComponent infoBox; + + public static void Start() + { + Submarine.Load("Content/Map/TutorialSub.gz"); + + Game1.GameSession = new GameSession(Submarine.Loaded, "", GameModePreset.list.Find(gm => gm.Name.ToLower()=="tutorial")); + + Game1.GameSession.StartShift(TimeSpan.Zero, "tutorial"); + + Game1.GameScreen.Select(); + } + + public TutorialMode(GameModePreset preset) + : base(preset) + { + CrewManager = new CrewManager(); + } + + public override void Start(TimeSpan duration) + { + base.Start(duration); + + WayPoint wayPoint = WayPoint.GetRandom(SpawnType.Cargo, null); + if (wayPoint==null) + { + DebugConsole.ThrowError("A waypoint with the spawntype ''cargo'' is required for the tutorial event"); + return; + } + + CharacterInfo charInfo = new CharacterInfo(Character.HumanConfigFile, "", Gender.None, JobPrefab.List.Find(jp => jp.Name=="Engineer")); + + Character character = new Character(charInfo, wayPoint.SimPosition); + Character.Controlled = character; + character.GiveJobItems(null); + + foreach (Item item in character.Inventory.items) + { + if (item == null || item.Name != "ID Card") continue; + + item.AddTag("com"); + item.AddTag("eng"); + + break; + } + + CrewManager.AddCharacter(character); + + CoroutineManager.StartCoroutine(UpdateState()); + } + + public override void Update(float deltaTime) + { + base.Update(deltaTime); + + CrewManager.Update(deltaTime); + if (infoBox!=null) infoBox.Update(deltaTime); + } + + private IEnumerable UpdateState() + { + + yield return new WaitForSeconds(4.0f); + + infoBox = CreateInfoFrame("Use WASD to move and mouse to look around"); + + yield return new WaitForSeconds(5.0f); + + //----------------------------------- + + infoBox = CreateInfoFrame("Open the door at your right side by highlighting the button next to it with your cursor and pressing E"); + + Door tutorialDoor = Item.itemList.Find(i => i.HasTag("tutorialdoor")).GetComponent(); + + while (!tutorialDoor.IsOpen) + { + yield return Status.Running; + } + + yield return new WaitForSeconds(2.0f); + + //----------------------------------- + + infoBox = CreateInfoFrame("Now it's time to power up the submarine. Go to the upper left corner of the submarine, where you'll find a nuclear reactor."); + + Reactor reactor = Item.itemList.Find(i => i.HasTag("tutorialreactor")).GetComponent(); + + while (Vector2.Distance(Character.Controlled.Position, reactor.Item.Position)>200.0f) + { + yield return Status.Running; + } + + infoBox = CreateInfoFrame("Select the reactor by walking next to it and pressing E."); + + while (Character.Controlled.SelectedConstruction != reactor.Item) + { + yield return Status.Running; + } + yield return new WaitForSeconds(0.5f); + + infoBox = CreateInfoFrame("This is the control panel of the reactor. Try turning it on by increasing the fission rate."); + + while (reactor.FissionRate <= 0.0f) + { + yield return Status.Running; + } + yield return new WaitForSeconds(0.5f); + + infoBox = CreateInfoFrame("The reactor core has started generating heat, which in turn generates power for the submarine. It won't generate much power at the moment, " + +" because the shutdown temperature is set to 500. When the temperature of the reactor raises higher than the shutdown temperature, the reactor will automatically start to cool itself down." + + " You should increase it to somewhere around 5000."); + + while (Math.Abs(reactor.ShutDownTemp-5000.0f) > 400.0f) + { + yield return Status.Running; + } + yield return new WaitForSeconds(0.5f); + + infoBox = CreateInfoFrame("The amount of power generated by the reactor should be kept close to the amount of power consumed by the devices in the submarine. " + +"If there's not enough power, devices won't function properly, and if there's too much power, some devices may be damaged. Turn on ''Automatic temperature control'' to " + +"make the reactor automatically adjust the temperature to a suitable level."); + + while (!reactor.AutoTemp) + { + yield return Status.Running; + } + yield return new WaitForSeconds(0.5f); + + infoBox = CreateInfoFrame("That's the basics you need to know to power up the reactor! Now that there's power available for the engines, let's try steering the sub. " + +"Deselect the reactor by pressing E and head to the command room at the left edge of the vessel."); + + Steering steering = Item.itemList.Find(i => i.HasTag("tutorialsteering")).GetComponent(); + Radar radar = steering.Item.GetComponent(); + + while (Vector2.Distance(Character.Controlled.Position, steering.Item.Position) > 150.0f) + { + yield return Status.Running; + } + + infoBox = CreateInfoFrame("Select the navigation terminal by walking next to it and pressing E."); + + while (Character.Controlled.SelectedConstruction != steering.Item) + { + yield return Status.Running; + } + yield return new WaitForSeconds(0.5f); + + infoBox = CreateInfoFrame("There seems to be something wrong with the navigation terminal."+ + " There's nothing on the monitor, so it's probably out of power. The reactor must still be" + +" running or the lights would've gone out, so it's most likely a problem with the wiring." + +" Deselect the terminal by pressing E to start checking the wiring."); + + while (Character.Controlled.SelectedConstruction == steering.Item) + { + yield return Status.Running; + } + yield return new WaitForSeconds(1.0f); + + infoBox = CreateInfoFrame("You need a screwdriver to check the wiring of the terminal." + + " Equip a screwdriver by pulling it to either of the slots with a hand symbol, and then select the terminal again by pressing E."); + + while (Character.Controlled.SelectedConstruction != steering.Item || + Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.Name == "Screwdriver") == null) + { + yield return Status.Running; + } + + + infoBox = CreateInfoFrame("Here you can see all the wires connected to the terminal. Apparently there's no wire" + + " going into the to the power connection - that's why the monitor isn't working." + + " You should find a piece of wire to connect it. Try searching some of the cabinets scattered around the sub."); + + while (Character.Controlled.Inventory.items.FirstOrDefault(i => i!=null && i.GetComponent()!=null)==null) + { + yield return Status.Running; + } + + infoBox = CreateInfoFrame("Head back to the navigation terminal to fix the wiring."); + + PowerTransfer junctionBox = Item.itemList.Find(i => i!=null && i.HasTag("tutorialjunctionbox")).GetComponent(); + + while ((Character.Controlled.SelectedConstruction != junctionBox.Item && + Character.Controlled.SelectedConstruction != steering.Item) || + Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.Name == "Screwdriver") == null) + { + yield return Status.Running; + } + + if (Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.GetComponent()!=null) == null) + { + infoBox = CreateInfoFrame("Equip the wire by dragging it to one of the slots with a hand symbol."); + + while (Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.GetComponent() != null) == null) + { + yield return Status.Running; + } + } + + infoBox = CreateInfoFrame("You can see the equipped wire at the middle of the connection panel. Drag it to the power connector."); + + var steeringConnection = steering.Item.Connections.Find(c => c.Name.Contains("power")); + var junctionConnection = junctionBox.Item.Connections.Find(c => c.Name.Contains("power")); + + while (steeringConnection.Wires.FirstOrDefault(w => w != null) == null) + { + yield return Status.Running; + + } + + infoBox = CreateInfoFrame("Now you have to connect the other end of the wire to a power source. " + + "The junction box in the room just below the command room should do."); + + while (Character.Controlled.SelectedConstruction!=null) + { + yield return Status.Running; + } + + yield return new WaitForSeconds(2.0f); + + infoBox = CreateInfoFrame("You can now move the other end of the wire around, and attach it on the wall by left clicking or " + + "remove the previous attachment by right clicking. Or you can just run the wire straight to the junction box and attach it " + + " the same way you did to the navigation terminal."); + + while (radar.Voltage<0.1f) + { + yield return Status.Running; + } + + infoBox = CreateInfoFrame("Great! Now we should be able to get moving."); + + + while (Character.Controlled.SelectedConstruction != steering.Item) + { + yield return Status.Running; + } + + infoBox = CreateInfoFrame("You can take a look at the area around the sub by pressing ''Activate Radar''."); + + while (!radar.IsActive) + { + yield return Status.Running; + } + yield return new WaitForSeconds(0.5f); + + infoBox = CreateInfoFrame("The white box in the middle is the submarine, and the white lines outside it are the walls of an underwater cavern. " + + "Try moving the submarine by clicking somewhere inside the rectangle and draggind the pointer to the direction you want to go to."); + + while (steering.CurrTargetVelocity == Vector2.Zero && steering.CurrTargetVelocity.Length() < 40.0f) + { + yield return Status.Running; + } + yield return new WaitForSeconds(4.0f); + + infoBox = CreateInfoFrame("The submarine moves up and down by pumping water in and out of the two ballast tanks at the bottom of the submarine. " + +"The engine at the back of the sub moves it forwards and backwards."); + + yield return new WaitForSeconds(8.0f); + + infoBox = CreateInfoFrame("Steer the submarine downwards, heading further into the cavern."); + + while (Submarine.Loaded.Position.Y > 31000.0f) + { + yield return Status.Running; + } + + var moloch = new Character("Content/Characters/Moloch/moloch.xml", steering.Item.SimPosition + Vector2.UnitX * 15.0f); + moloch.PlaySound(AIController.AiState.Attack); + + //moloch.AIController. + + infoBox = CreateInfoFrame("Uh-oh... Something enormous just appeared on the radar."); + + Structure window = null; + foreach (Structure s in Structure.wallList) + { + if (s.CastShadow) continue; + + if (window == null || s.Rect.Right > window.Rect.Right) window = s; + } + + bool broken = false; + do + { + moloch.AIController.SelectTarget(steering.Item); + for (int i = 0; i < window.SectionCount; i++) + { + if (!window.SectionHasHole(i)) continue; + broken = true; + break; + } + + yield return new WaitForSeconds(1.0f); + } while (!broken); + + yield return Status.Success; + } + + public override void Draw(SpriteBatch spriteBatch) + { + base.Draw(spriteBatch); + + CrewManager.Draw(spriteBatch); + if (infoBox != null) infoBox.Draw(spriteBatch); + } + + private GUIComponent CreateInfoFrame(string text) + { + int width = 300; + int height = 80; + + string wrappedText = ToolBox.WrapText(text, width, GUI.Font); + + height += wrappedText.Split('\n').Length*25; + + var infoBlock = new GUIFrame(new Rectangle(-20, 20, width, height), null, Alignment.TopRight, GUI.style); + //infoBlock.Color = infoBlock.Color * 0.8f; + infoBlock.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f); + infoBlock.Flash(Color.Green); + + new GUITextBlock(new Rectangle(10, 10, width - 40, height), text, GUI.style, infoBlock, true); + + + GUI.PlayMessageSound(); + + return infoBlock; + } + } } diff --git a/Subsurface/Source/Items/Components/Machines/Radar.cs b/Subsurface/Source/Items/Components/Machines/Radar.cs index 89a995781..3b31c1d74 100644 --- a/Subsurface/Source/Items/Components/Machines/Radar.cs +++ b/Subsurface/Source/Items/Components/Machines/Radar.cs @@ -148,43 +148,16 @@ namespace Subsurface.Items.Components screenOverlay.Draw(spriteBatch, center, 0.0f, rect.Width/screenOverlay.size.X); } - //if (Level.Loaded != null) - //{ + if (Game1.GameSession == null) return; - // for (int i = 0; i < 2; i++) - // { - // Vector2 targetPos = (i == 0) ? Level.Loaded.StartPosition : Level.Loaded.EndPosition; - // targetPos += Level.Loaded.Position; - // float dist = targetPos.Length(); + DrawMarker(spriteBatch, + (Game1.GameSession.Map == null) ? "Start" : Game1.GameSession.Map.CurrentLocation.Name, + (Level.Loaded.StartPosition + Level.Loaded.Position), displayScale, center, (rect.Width * 0.55f)); - // targetPos.Y = -targetPos.Y; - // Vector2 markerPos = Vector2.Normalize(targetPos) * (rect.Width * 0.55f); - // markerPos += center; - - // GUI.DrawRectangle(spriteBatch, new Rectangle((int)markerPos.X, (int)markerPos.Y, 5, 5), Color.LightGreen); - - // string label; - // if (Game1.GameSession.Map!=null) - // { - // label = (i == 0) ? Game1.GameSession.Map.CurrentLocation.Name : Game1.GameSession.Map.SelectedLocation.Name; - // } - // else - // { - // label = (i == 0) ? "Start" : "End"; - // } - - // spriteBatch.DrawString(GUI.SmallFont, label, new Vector2(markerPos.X + 10, markerPos.Y), Color.LightGreen); - // spriteBatch.DrawString(GUI.SmallFont, (int)(dist / 80.0f) + " m", new Vector2(markerPos.X + 10, markerPos.Y + 15), Color.LightGreen); - // } - - DrawMarker(spriteBatch, - (Game1.GameSession.Map == null) ? "Start" : Game1.GameSession.Map.CurrentLocation.Name, - (Level.Loaded.StartPosition + Level.Loaded.Position), displayScale, center, (rect.Width * 0.55f)); - - DrawMarker(spriteBatch, - (Game1.GameSession.Map == null) ? "End" : Game1.GameSession.Map.SelectedLocation.Name, - (Level.Loaded.EndPosition + Level.Loaded.Position), displayScale, center, (rect.Width * 0.55f)); + DrawMarker(spriteBatch, + (Game1.GameSession.Map == null) ? "End" : Game1.GameSession.Map.SelectedLocation.Name, + (Level.Loaded.EndPosition + Level.Loaded.Position), displayScale, center, (rect.Width * 0.55f)); if (Game1.GameSession.Quest != null) { diff --git a/Subsurface/Source/Items/Components/Machines/Reactor.cs b/Subsurface/Source/Items/Components/Machines/Reactor.cs index 316512dbc..afe8c36d5 100644 --- a/Subsurface/Source/Items/Components/Machines/Reactor.cs +++ b/Subsurface/Source/Items/Components/Machines/Reactor.cs @@ -88,10 +88,20 @@ namespace Subsurface.Items.Components return (temperature > 0.0f); } + public bool AutoTemp + { + get { return autoTemp; } + } + public float ExtraCooling { get; set; } public float AvailableFuel { get; set; } + public float ShutDownTemp + { + get { return shutDownTemp; } + } + public Reactor(Item item, XElement element) : base(item, element) { diff --git a/Subsurface/Source/Items/Components/Machines/Steering.cs b/Subsurface/Source/Items/Components/Machines/Steering.cs index 5b3054390..0caf77329 100644 --- a/Subsurface/Source/Items/Components/Machines/Steering.cs +++ b/Subsurface/Source/Items/Components/Machines/Steering.cs @@ -57,6 +57,11 @@ namespace Subsurface.Items.Components } } + public Vector2 CurrTargetVelocity + { + get { return targetVelocity; } + } + public Steering(Item item, XElement element) : base(item, element) { diff --git a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs index 647258840..6bb00eefa 100644 --- a/Subsurface/Source/Items/Components/Power/PowerTransfer.cs +++ b/Subsurface/Source/Items/Components/Power/PowerTransfer.cs @@ -135,7 +135,7 @@ namespace Subsurface.Items.Components { base.ReceiveSignal(signal, connection, sender, power); - if (connection.Name == "signal") + if (connection.Name.Length>5 && connection.Name.Substring(0, 6).ToLower() == "signal") { connection.SendSignal(signal, sender, 0.0f); } diff --git a/Subsurface/Source/Items/Components/Signal/Connection.cs b/Subsurface/Source/Items/Components/Signal/Connection.cs index c790acd00..86ddc2556 100644 --- a/Subsurface/Source/Items/Components/Signal/Connection.cs +++ b/Subsurface/Source/Items/Components/Signal/Connection.cs @@ -132,21 +132,6 @@ namespace Subsurface.Items.Components Wires[index] = wire; } - //public bool AddLink(Item connectedItem, Connection otherConnection) - //{ - // if (linked.Contains(connectedItem)) return false; - - // for (int i = 0; i DimLight() + private IEnumerable DimLight() { float currBrightness= 1.0f; float startRange = light.Range; diff --git a/Subsurface/Source/Map/IDamageable.cs b/Subsurface/Source/Map/IDamageable.cs index 29af336d4..bfd5ae1b0 100644 --- a/Subsurface/Source/Map/IDamageable.cs +++ b/Subsurface/Source/Map/IDamageable.cs @@ -14,6 +14,11 @@ namespace Subsurface get; } + AITarget AiTarget + { + get; + } + AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, float stun, bool playSound=true); } } diff --git a/Subsurface/Source/Map/Lights/LightManager.cs b/Subsurface/Source/Map/Lights/LightManager.cs index c55d3c120..0787febbf 100644 --- a/Subsurface/Source/Map/Lights/LightManager.cs +++ b/Subsurface/Source/Map/Lights/LightManager.cs @@ -57,9 +57,6 @@ namespace Subsurface.Lights public void DrawLOS(GraphicsDevice graphics, Camera cam, Vector2 pos) { - Stopwatch sw = new Stopwatch(); - sw.Start(); - Rectangle camView = new Rectangle(cam.WorldView.X, cam.WorldView.Y - cam.WorldView.Height, cam.WorldView.Width, cam.WorldView.Height); if (!LosEnabled) return; @@ -70,15 +67,10 @@ namespace Subsurface.Lights convexHull.DrawShadows(graphics, cam, pos); } - long elapsed = sw.ElapsedTicks; - Debug.WriteLine("los: "+elapsed); } public void DrawLightmap(GraphicsDevice graphics, SpriteBatch spriteBatch, Camera cam) { - Stopwatch sw = new Stopwatch(); - sw.Start(); - graphics.SetRenderTarget(lightMap); Rectangle viewRect = cam.WorldView; @@ -116,10 +108,6 @@ namespace Subsurface.Lights //clear alpha, to avoid messing stuff up later ClearAlphaToOne(graphics, spriteBatch); graphics.SetRenderTarget(null); - - - long elapsed = sw.ElapsedTicks; - Debug.WriteLine("lights: " + elapsed); } private void ClearAlphaToOne(GraphicsDevice graphics, SpriteBatch spriteBatch) diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 4b5f48f63..2b4defea3 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -98,6 +98,10 @@ namespace Subsurface get { return prefab.MaxHealth; } } + public AITarget AiTarget + { + get { return null;} + } public override void Move(Vector2 amount) { diff --git a/Subsurface/Source/Networking/GameClient.cs b/Subsurface/Source/Networking/GameClient.cs index 638399375..42d4cf342 100644 --- a/Subsurface/Source/Networking/GameClient.cs +++ b/Subsurface/Source/Networking/GameClient.cs @@ -136,7 +136,7 @@ namespace Subsurface.Networking } // Before main looping starts, we loop here and wait for approval message - private IEnumerable WaitForStartingInfo() + private IEnumerable WaitForStartingInfo() { // When this is set to true, we are approved and ready to go bool CanStart = false; diff --git a/Subsurface/Source/Screens/GameScreen.cs b/Subsurface/Source/Screens/GameScreen.cs index 5aa1faa04..366965bb4 100644 --- a/Subsurface/Source/Screens/GameScreen.cs +++ b/Subsurface/Source/Screens/GameScreen.cs @@ -112,7 +112,6 @@ namespace Subsurface DrawMap(graphics, spriteBatch); spriteBatch.Begin(); - if (Game1.GameSession != null) Game1.GameSession.Draw(spriteBatch); if (Character.Controlled != null && Character.Controlled.SelectedConstruction != null) { @@ -126,6 +125,8 @@ namespace Subsurface } } + if (Game1.GameSession != null) Game1.GameSession.Draw(spriteBatch); + GUI.Draw((float)deltaTime, spriteBatch, cam); if (PlayerInput.GetMouseState.LeftButton != ButtonState.Pressed) Inventory.draggingItem = null; diff --git a/Subsurface/Source/Screens/MainMenu.cs b/Subsurface/Source/Screens/MainMenu.cs index 5c5531ff4..c9f9ae9d5 100644 --- a/Subsurface/Source/Screens/MainMenu.cs +++ b/Subsurface/Source/Screens/MainMenu.cs @@ -38,26 +38,29 @@ namespace Subsurface menuTabs[(int)Tabs.Main] = new GUIFrame(panelRect, GUI.style); //menuTabs[(int)Tabs.Main].Padding = GUI.style.smallPadding; - GUIButton button = new GUIButton(new Rectangle(0, 0, 0, 30), "New Game", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); + GUIButton button = new GUIButton(new Rectangle(0, 0, 0, 30), "Tutorial", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); + button.OnClicked = TutorialButtonClicked; + + button = new GUIButton(new Rectangle(0, 70, 0, 30), "New Game", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); button.UserData = (int)Tabs.NewGame; button.OnClicked = SelectTab; //button.Enabled = false; - button = new GUIButton(new Rectangle(0, 60, 0, 30), "Load Game", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); + button = new GUIButton(new Rectangle(0, 130, 0, 30), "Load Game", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); button.UserData = (int)Tabs.LoadGame; button.OnClicked = SelectTab; //button.Enabled = false; - button = new GUIButton(new Rectangle(0, 120, 0, 30), "Join Server", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); + button = new GUIButton(new Rectangle(0, 200, 0, 30), "Join Server", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); //button.UserData = (int)Tabs.JoinServer; button.OnClicked = JoinServerClicked; - button = new GUIButton(new Rectangle(0, 180, 0, 30), "Host Server", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); + button = new GUIButton(new Rectangle(0, 260, 0, 30), "Host Server", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); button.UserData = (int)Tabs.HostServer; button.OnClicked = SelectTab; //button.Enabled = false; - button = new GUIButton(new Rectangle(0, 240, 0, 30), "Quit", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); + button = new GUIButton(new Rectangle(0, 330, 0, 30), "Quit", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.Main]); button.OnClicked = QuitClicked; //---------------------------------------------------------------------- @@ -105,62 +108,6 @@ namespace Subsurface menuTabs[(int)Tabs.LoadGame] = new GUIFrame(panelRect, GUI.style); //menuTabs[(int)Tabs.LoadGame].Padding = GUI.style.smallPadding; - //new GUITextBlock(new Rectangle(0, 0, 0, 30), "Load Game", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.LoadGame]); - - ////if (!Directory.Exists(SaveUtil.SaveFolder)) - ////{ - //// DebugConsole.ThrowError("Save folder ''"+SaveUtil.SaveFolder+" not found! Attempting to create a new folder"); - //// try - //// { - //// Directory.CreateDirectory(SaveUtil.SaveFolder); - //// } - //// catch (Exception e) - //// { - //// DebugConsole.ThrowError("Failed to create the folder ''"+SaveUtil.SaveFolder+"''!", e); - //// } - ////} - - //string[] saveFiles = SaveUtil.GetSaveFiles();//Directory.GetFiles(SaveUtil.SaveFolder, "*.save"); - - ////new GUITextBlock(new Rectangle(0, 30, 0, 30), "Selected map:", Color.Transparent, Color.Black, Alignment.Left, menuTabs[(int)Tabs.NewGame]); - //saveList = new GUIListBox(new Rectangle(0, 60, 200, 360), Color.White, GUI.style, menuTabs[(int)Tabs.LoadGame]); - - //foreach (string saveFile in saveFiles) - //{ - // GUITextBlock textBlock = new GUITextBlock( - // new Rectangle(0, 0, 0, 25), - // saveFile, - // GUI.style, - // Alignment.Left, - // Alignment.Left, - // saveList); - // textBlock.Padding = new Vector4(10.0f, 0.0f, 0.0f, 0.0f); - // textBlock.UserData = saveFile; - //} - - //button = new GUIButton(new Rectangle(0, 0, 100, 30), "Start",Alignment.Right | Alignment.Bottom, GUI.style, menuTabs[(int)Tabs.LoadGame]); - //button.OnClicked = LoadGame; - - //---------------------------------------------------------------------- - - //menuTabs[(int)Tabs.JoinServer] = new GUIFrame(panelRect, GUI.style); - ////menuTabs[(int)Tabs.JoinServer].Padding = GUI.style.smallPadding; - - //new GUITextBlock(new Rectangle(0, 0, 0, 30), "Join Server", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.JoinServer]); - - //new GUITextBlock(new Rectangle(0, 30, 0, 30), "Your Name:", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.JoinServer]); - //clientNameBox = new GUITextBox(new Rectangle(0, 60, 200, 30), Color.White, Color.Black, Alignment.CenterX, Alignment.CenterX, null, menuTabs[(int)Tabs.JoinServer]); - - //new GUITextBlock(new Rectangle(0, 100, 0, 30), "Server IP:", GUI.style, Alignment.CenterX, Alignment.CenterX, menuTabs[(int)Tabs.JoinServer]); - //ipBox = new GUITextBox(new Rectangle(0, 130, 200, 30), Color.White, Color.Black, Alignment.CenterX, Alignment.CenterX, null, menuTabs[(int)Tabs.JoinServer]); - - //GUIButton joinButton = new GUIButton(new Rectangle(0, 200, 200, 30), "Join", Alignment.CenterX, GUI.style, menuTabs[(int)Tabs.JoinServer]); - //joinButton.OnClicked = JoinServer; - - //GUIButton serverListButton = new GUIButton(new Rectangle(0, 0, 230, 30), "Server List", Alignment.BottomCenter, GUI.style, menuTabs[(int)Tabs.JoinServer]); - //serverListButton.OnClicked = ServerListClicked; - - //---------------------------------------------------------------------- menuTabs[(int)Tabs.HostServer] = new GUIFrame(panelRect, GUI.style); //menuTabs[(int)Tabs.JoinServer].Padding = GUI.style.smallPadding; @@ -199,6 +146,13 @@ namespace Subsurface return true; } + private bool TutorialButtonClicked(GUIButton button, object obj) + { + TutorialMode.Start(); + + return true; + } + private bool JoinServerClicked(GUIButton button, object obj) { Game1.ServerListScreen.Select(); diff --git a/Subsurface/Source/Sounds/AmbientSoundManager.cs b/Subsurface/Source/Sounds/AmbientSoundManager.cs index 0482514c5..a984733c5 100644 --- a/Subsurface/Source/Sounds/AmbientSoundManager.cs +++ b/Subsurface/Source/Sounds/AmbientSoundManager.cs @@ -67,7 +67,7 @@ namespace Subsurface private static Sound startDrone; - public static IEnumerable Init() + public static IEnumerable Init() { diff --git a/Subsurface/Subsurface.csproj b/Subsurface/Subsurface.csproj index 406950bd3..58023277f 100644 --- a/Subsurface/Subsurface.csproj +++ b/Subsurface/Subsurface.csproj @@ -725,7 +725,16 @@ - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + PreserveNewest diff --git a/Subsurface_Solution.v12.suo b/Subsurface_Solution.v12.suo index 8cb8cfcd6..2c60509ce 100644 Binary files a/Subsurface_Solution.v12.suo and b/Subsurface_Solution.v12.suo differ