Renamed project folders from Subsurface to Barotrauma
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CargoManager
|
||||
{
|
||||
private List<ItemPrefab> purchasedItems;
|
||||
|
||||
public CargoManager()
|
||||
{
|
||||
purchasedItems = new List<ItemPrefab>();
|
||||
}
|
||||
|
||||
public void AddItem(ItemPrefab item)
|
||||
{
|
||||
purchasedItems.Add(item);
|
||||
}
|
||||
|
||||
public void CreateItems()
|
||||
{
|
||||
WayPoint wp = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub);
|
||||
|
||||
if (wp==null)
|
||||
{
|
||||
DebugConsole.ThrowError("The submarine must have a waypoint marked as Cargo for bought items to be placed correctly!");
|
||||
return;
|
||||
}
|
||||
|
||||
Hull cargoRoom = Hull.FindHull(wp.WorldPosition);
|
||||
|
||||
if (cargoRoom == null)
|
||||
{
|
||||
DebugConsole.ThrowError("A waypoint marked as Cargo must be placed inside a room!");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (ItemPrefab prefab in purchasedItems)
|
||||
{
|
||||
Vector2 position = new Vector2(
|
||||
Rand.Range(cargoRoom.Rect.X + 20, cargoRoom.Rect.Right - 20),
|
||||
cargoRoom.Rect.Y - cargoRoom.Rect.Height + prefab.Size.Y/2);
|
||||
|
||||
new Item(prefab, position, wp.Submarine);
|
||||
}
|
||||
|
||||
purchasedItems.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,359 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CrewManager
|
||||
{
|
||||
public List<Character> characters;
|
||||
public List<CharacterInfo> characterInfos;
|
||||
|
||||
public int WinningTeam = 1;
|
||||
|
||||
private int money;
|
||||
|
||||
private GUIFrame guiFrame;
|
||||
private GUIListBox listBox, orderListBox;
|
||||
|
||||
private CrewCommander commander;
|
||||
|
||||
public CrewCommander CrewCommander
|
||||
{
|
||||
get { return commander; }
|
||||
}
|
||||
|
||||
public int Money
|
||||
{
|
||||
get { return money; }
|
||||
set { money = (int)Math.Max(value, 0.0f); }
|
||||
}
|
||||
|
||||
public CrewManager()
|
||||
{
|
||||
characters = new List<Character>();
|
||||
characterInfos = new List<CharacterInfo>();
|
||||
|
||||
guiFrame = new GUIFrame(new Rectangle(0, 50, 150, 450), Color.Transparent);
|
||||
guiFrame.Padding = Vector4.One * 5.0f;
|
||||
|
||||
listBox = new GUIListBox(new Rectangle(45, 30, 150, 0), Color.Transparent, null, guiFrame);
|
||||
listBox.ScrollBarEnabled = false;
|
||||
listBox.OnSelected = SelectCharacter;
|
||||
|
||||
orderListBox = new GUIListBox(new Rectangle(5, 30, 30, 0), Color.Transparent, null, guiFrame);
|
||||
orderListBox.ScrollBarEnabled = false;
|
||||
orderListBox.OnSelected = SelectCharacterOrder;
|
||||
|
||||
commander = new CrewCommander(this);
|
||||
|
||||
money = 10000;
|
||||
}
|
||||
|
||||
public CrewManager(XElement element)
|
||||
: this()
|
||||
{
|
||||
money = ToolBox.GetAttributeInt(element, "money", 0);
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "character") continue;
|
||||
|
||||
characterInfos.Add(new CharacterInfo(subElement));
|
||||
}
|
||||
}
|
||||
|
||||
public bool SelectCharacter(GUIComponent component, object selection)
|
||||
{
|
||||
//listBox.Select(selection);
|
||||
Character character = selection as Character;
|
||||
|
||||
if (character == null || character.IsDead || character.IsUnconscious) return false;
|
||||
|
||||
if (characters.Contains(character))
|
||||
{
|
||||
Character.Controlled = character;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetCharacterOrder(Character character, Order order)
|
||||
{
|
||||
if (order == null) return;
|
||||
|
||||
var characterFrame = listBox.FindChild(character);
|
||||
|
||||
if (characterFrame == null) return;
|
||||
|
||||
int characterIndex = listBox.children.IndexOf(characterFrame);
|
||||
|
||||
orderListBox.children[characterIndex].ClearChildren();
|
||||
|
||||
var img = new GUIImage(new Rectangle(0, 0, 30, 30), order.SymbolSprite, Alignment.Center, orderListBox.children[characterIndex]);
|
||||
img.Scale = 30.0f / img.SourceRect.Width;
|
||||
img.Color = order.Color;
|
||||
img.CanBeFocused = false;
|
||||
|
||||
orderListBox.children[characterIndex].ToolTip = "Order: " + order.Name;
|
||||
}
|
||||
|
||||
public bool SelectCharacterOrder(GUIComponent component, object selection)
|
||||
{
|
||||
commander.ToggleGUIFrame();
|
||||
|
||||
int orderIndex = orderListBox.children.IndexOf(component);
|
||||
if (orderIndex < 0 || orderIndex >= listBox.children.Count) return false;
|
||||
|
||||
var characterFrame = listBox.children[orderIndex];
|
||||
if (characterFrame == null) return false;
|
||||
|
||||
commander.SelectCharacter(characterFrame.UserData as Character);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void AddCharacter(Character character)
|
||||
{
|
||||
characters.Add(character);
|
||||
if (!characterInfos.Contains(character.Info))
|
||||
{
|
||||
characterInfos.Add(character.Info);
|
||||
}
|
||||
|
||||
if (character is AICharacter)
|
||||
{
|
||||
commander.UpdateCharacters();
|
||||
}
|
||||
|
||||
character.Info.CreateCharacterFrame(listBox, character.Info.Name.Replace(' ', '\n'), character);
|
||||
|
||||
GUIFrame orderFrame = new GUIFrame(new Rectangle(0, 0, 40, 40), Color.Transparent, "ListBoxElement", orderListBox);
|
||||
orderFrame.UserData = character;
|
||||
|
||||
var ai = character.AIController as HumanAIController;
|
||||
if (ai == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in crewmanager - attempted to give orders to a character with no HumanAIController");
|
||||
return;
|
||||
}
|
||||
SetCharacterOrder(character, ai.CurrentOrder);
|
||||
}
|
||||
|
||||
public void AddToGUIUpdateList()
|
||||
{
|
||||
guiFrame.AddToGUIUpdateList();
|
||||
if (commander.Frame != null) commander.Frame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
guiFrame.Update(deltaTime);
|
||||
|
||||
//TODO: implement AI commands in multiplayer?
|
||||
if (GameMain.NetworkMember == null &&
|
||||
GameMain.Config.KeyBind(InputType.CrewOrders).IsHit())
|
||||
{
|
||||
//deselect construction unless it's the ladders the character is climbing
|
||||
if (!commander.IsOpen && Character.Controlled != null &&
|
||||
Character.Controlled.SelectedConstruction != null &&
|
||||
Character.Controlled.SelectedConstruction.GetComponent<Items.Components.Ladder>() == null)
|
||||
{
|
||||
Character.Controlled.SelectedConstruction = null;
|
||||
}
|
||||
|
||||
//only allow opening the command UI if there are AICharacters in the crew
|
||||
if (commander.IsOpen || characters.Any(c => c is AICharacter)) commander.ToggleGUIFrame();
|
||||
}
|
||||
|
||||
if (commander.Frame != null) commander.Frame.Update(deltaTime);
|
||||
}
|
||||
|
||||
public void ReviveCharacter(Character revivedCharacter)
|
||||
{
|
||||
GUIComponent characterBlock = listBox.GetChild(revivedCharacter) as GUIComponent;
|
||||
if (characterBlock != null) characterBlock.Color = Color.Transparent;
|
||||
|
||||
if (revivedCharacter is AICharacter)
|
||||
{
|
||||
commander.UpdateCharacters();
|
||||
}
|
||||
}
|
||||
|
||||
public void KillCharacter(Character killedCharacter)
|
||||
{
|
||||
GUIComponent characterBlock = listBox.GetChild(killedCharacter) as GUIComponent;
|
||||
if (characterBlock != null) characterBlock.Color = Color.DarkRed * 0.5f;
|
||||
|
||||
if (killedCharacter is AICharacter)
|
||||
{
|
||||
commander.UpdateCharacters();
|
||||
}
|
||||
//if (characters.Find(c => !c.IsDead)==null)
|
||||
//{
|
||||
// Game1.GameSession.EndShift(null, null);
|
||||
//}
|
||||
}
|
||||
|
||||
public void CreateCrewFrame(List<Character> crew, GUIFrame crewFrame)
|
||||
{
|
||||
List<byte> teamIDs = crew.Select(c => c.TeamID).Distinct().ToList();
|
||||
|
||||
if (!teamIDs.Any()) teamIDs.Add(0);
|
||||
|
||||
int listBoxHeight = 300 / teamIDs.Count;
|
||||
|
||||
int y = 20;
|
||||
for (int i = 0; i < teamIDs.Count; i++)
|
||||
{
|
||||
if (teamIDs.Count > 1)
|
||||
{
|
||||
new GUITextBlock(new Rectangle(0, y - 20, 100, 20), CombatMission.GetTeamName(teamIDs[i]), "", crewFrame);
|
||||
}
|
||||
|
||||
GUIListBox crewList = new GUIListBox(new Rectangle(0, y, 280, listBoxHeight), Color.White * 0.7f, "", crewFrame);
|
||||
crewList.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
|
||||
crewList.OnSelected = (component, obj) =>
|
||||
{
|
||||
SelectCrewCharacter(component.UserData as Character, crewList);
|
||||
return true;
|
||||
};
|
||||
|
||||
foreach (Character character in crew.FindAll(c => c.TeamID == teamIDs[i]))
|
||||
{
|
||||
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, "ListBoxElement", crewList);
|
||||
frame.UserData = character;
|
||||
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
frame.Color = (GameMain.NetworkMember != null && GameMain.NetworkMember.Character == character) ? Color.Gold * 0.2f : Color.Transparent;
|
||||
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(40, 0, 0, 25),
|
||||
ToolBox.LimitString(character.Info.Name + " (" + character.Info.Job.Name + ")", GUI.Font, frame.Rect.Width-20),
|
||||
null,null,
|
||||
Alignment.Left, Alignment.Left,
|
||||
"", frame);
|
||||
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
|
||||
|
||||
new GUIImage(new Rectangle(-10, 0, 0, 0), character.AnimController.Limbs[0].sprite, Alignment.Left, frame);
|
||||
}
|
||||
|
||||
y += crewList.Rect.Height + 30;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected virtual bool SelectCrewCharacter(Character character, GUIComponent crewList)
|
||||
{
|
||||
if (character == null) return false;
|
||||
|
||||
GUIComponent existingFrame = crewList.Parent.FindChild("selectedcharacter");
|
||||
if (existingFrame != null) crewList.Parent.RemoveChild(existingFrame);
|
||||
|
||||
var previewPlayer = new GUIFrame(
|
||||
new Rectangle(0, 0, 230, 300),
|
||||
new Color(0.0f, 0.0f, 0.0f, 0.8f), Alignment.TopRight, "", crewList.Parent);
|
||||
previewPlayer.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
previewPlayer.UserData = "selectedcharacter";
|
||||
|
||||
character.Info.CreateInfoFrame(previewPlayer);
|
||||
|
||||
if (GameMain.NetworkMember != null) GameMain.NetworkMember.SelectCrewCharacter(character, crewList);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//private bool ToggleCrewFrame(GUIButton button, object obj)
|
||||
//{
|
||||
// if (crewFrame == null) CreateCrewFrame(characters);
|
||||
|
||||
// crewFrameOpen = !crewFrameOpen;
|
||||
// return true;
|
||||
//}
|
||||
|
||||
public void StartShift()
|
||||
{
|
||||
listBox.ClearChildren();
|
||||
characters.Clear();
|
||||
|
||||
WayPoint[] waypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub);
|
||||
|
||||
for (int i = 0; i < waypoints.Length; i++)
|
||||
{
|
||||
Character character;
|
||||
|
||||
if (characterInfos[i].HullID != null)
|
||||
{
|
||||
var hull = Entity.FindEntityByID((ushort)characterInfos[i].HullID) as Hull;
|
||||
if (hull == null) continue;
|
||||
character = Character.Create(characterInfos[i], hull.WorldPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
character = Character.Create(characterInfos[i], waypoints[i].WorldPosition);
|
||||
Character.Controlled = character;
|
||||
|
||||
if (character.Info != null && !character.Info.StartItemsGiven)
|
||||
{
|
||||
character.GiveJobItems(waypoints[i]);
|
||||
character.Info.StartItemsGiven = true;
|
||||
}
|
||||
}
|
||||
|
||||
AddCharacter(character);
|
||||
}
|
||||
|
||||
if (characters.Any()) listBox.Select(0);// SelectCharacter(null, characters[0]);
|
||||
}
|
||||
|
||||
public void EndShift()
|
||||
{
|
||||
foreach (Character c in characters)
|
||||
{
|
||||
if (!c.IsDead)
|
||||
{
|
||||
c.Info.UpdateCharacterItems();
|
||||
continue;
|
||||
}
|
||||
|
||||
CharacterInfo deadInfo = characterInfos.Find(x => c.Info == x);
|
||||
if (deadInfo != null) characterInfos.Remove(deadInfo);
|
||||
}
|
||||
|
||||
characters.Clear();
|
||||
listBox.ClearChildren();
|
||||
orderListBox.ClearChildren();
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (commander.IsOpen)
|
||||
{
|
||||
commander.Draw(spriteBatch);
|
||||
}
|
||||
else
|
||||
{
|
||||
guiFrame.Draw(spriteBatch);
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(XElement parentElement)
|
||||
{
|
||||
XElement element = new XElement("crew");
|
||||
|
||||
element.Add(new XAttribute("money", money));
|
||||
|
||||
foreach (CharacterInfo ci in characterInfos)
|
||||
{
|
||||
ci.Save(element);
|
||||
}
|
||||
|
||||
parentElement.Add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class GameMode
|
||||
{
|
||||
public static List<GameModePreset> PresetList = new List<GameModePreset>();
|
||||
|
||||
protected DateTime startTime;
|
||||
|
||||
//public readonly bool IsSinglePlayer;
|
||||
|
||||
protected bool isRunning;
|
||||
|
||||
//protected string name;
|
||||
|
||||
protected GameModePreset preset;
|
||||
|
||||
private string endMessage;
|
||||
|
||||
public virtual Mission Mission
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
public bool IsRunning
|
||||
{
|
||||
get { return isRunning; }
|
||||
}
|
||||
|
||||
public bool IsSinglePlayer
|
||||
{
|
||||
get { return preset.IsSinglePlayer; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return preset.Name; }
|
||||
}
|
||||
|
||||
public string EndMessage
|
||||
{
|
||||
get { return endMessage; }
|
||||
}
|
||||
|
||||
public GameModePreset Preset
|
||||
{
|
||||
get { return preset; }
|
||||
}
|
||||
|
||||
public GameMode(GameModePreset preset, object param)
|
||||
{
|
||||
this.preset = preset;
|
||||
}
|
||||
|
||||
public virtual void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
startTime = DateTime.Now;
|
||||
//if (duration!=TimeSpan.Zero)
|
||||
//{
|
||||
// endTime = startTime + duration;
|
||||
// this.duration = duration;
|
||||
|
||||
// timerBar = new GUIProgressBar(new Rectangle(GameMain.GraphicsWidth - 120, 20, 100, 25), Color.Gold, 0.0f, null);
|
||||
//}
|
||||
|
||||
endMessage = "The round has ended!";
|
||||
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
public virtual void MsgBox() { }
|
||||
|
||||
public virtual void AddToGUIUpdateList() { }
|
||||
|
||||
public virtual void Update(float deltaTime)
|
||||
{
|
||||
//if (!isRunning) return;
|
||||
|
||||
//if (duration != TimeSpan.Zero)
|
||||
//{
|
||||
// double elapsedTime = (DateTime.Now - startTime).TotalSeconds;
|
||||
// timerBar.BarSize = (float)(elapsedTime / duration.TotalSeconds);
|
||||
//}
|
||||
//if (DateTime.Now >= endTime)
|
||||
//{
|
||||
// End(endMessage);
|
||||
//}
|
||||
}
|
||||
|
||||
public virtual void End(string endMessage = "")
|
||||
{
|
||||
isRunning = false;
|
||||
|
||||
if (endMessage != "" || this.endMessage == null) this.endMessage = endMessage;
|
||||
|
||||
GameMain.GameSession.EndShift(endMessage);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class GameModePreset
|
||||
{
|
||||
public static List<GameModePreset> list = new List<GameModePreset>();
|
||||
|
||||
public ConstructorInfo Constructor;
|
||||
public string Name;
|
||||
public bool IsSinglePlayer;
|
||||
|
||||
public string Description;
|
||||
|
||||
public GameModePreset(string name, Type type, bool isSinglePlayer = false)
|
||||
{
|
||||
this.Name = name;
|
||||
|
||||
Constructor = type.GetConstructor(new Type[] { typeof(GameModePreset), typeof(object) });
|
||||
|
||||
IsSinglePlayer = isSinglePlayer;
|
||||
|
||||
list.Add(this);
|
||||
}
|
||||
|
||||
public GameMode Instantiate(object param)
|
||||
{
|
||||
object[] lobject = new object[] { this, param };
|
||||
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("Mission", typeof(MissionMode), 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.";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class MissionMode : GameMode
|
||||
{
|
||||
private Mission mission;
|
||||
|
||||
public override Mission Mission
|
||||
{
|
||||
get
|
||||
{
|
||||
return mission;
|
||||
}
|
||||
}
|
||||
|
||||
public MissionMode(GameModePreset preset, object param)
|
||||
: base(preset, param)
|
||||
{
|
||||
Location[] locations = { GameMain.GameSession.StartLocation, GameMain.GameSession.EndLocation };
|
||||
|
||||
MTRandom rand = new MTRandom(ToolBox.StringToInt(GameMain.NetLobbyScreen.LevelSeed));
|
||||
mission = Mission.LoadRandom(locations, rand, param as string);
|
||||
}
|
||||
|
||||
public override void MsgBox()
|
||||
{
|
||||
if (mission == null) return;
|
||||
|
||||
var missionMsg = new GUIMessageBox(mission.Name, mission.Description, 400, 400);
|
||||
missionMsg.UserData = "missionstartmessage";
|
||||
|
||||
Networking.GameServer.Log("Mission: " + mission.Name, Networking.ServerLog.MessageType.ServerMessage);
|
||||
Networking.GameServer.Log(mission.Description, Networking.ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,411 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class SinglePlayerMode : GameMode
|
||||
{
|
||||
//private const int StartCharacterAmount = 3;
|
||||
|
||||
//public readonly CrewManager CrewManager;
|
||||
//public readonly HireManager hireManager;
|
||||
|
||||
private GUIButton endShiftButton;
|
||||
|
||||
public readonly CargoManager CargoManager;
|
||||
|
||||
public Map Map;
|
||||
|
||||
private bool crewDead;
|
||||
private float endTimer;
|
||||
|
||||
private bool savedOnStart;
|
||||
|
||||
private List<Submarine> subsToLeaveBehind;
|
||||
|
||||
private Submarine leavingSub;
|
||||
private bool atEndPosition;
|
||||
|
||||
public override Mission Mission
|
||||
{
|
||||
get
|
||||
{
|
||||
return Map.SelectedConnection.Mission;
|
||||
}
|
||||
}
|
||||
|
||||
public int Money
|
||||
{
|
||||
get { return GameMain.GameSession.CrewManager.Money; }
|
||||
set { GameMain.GameSession.CrewManager.Money = value; }
|
||||
}
|
||||
|
||||
private CrewManager CrewManager
|
||||
{
|
||||
get { return GameMain.GameSession.CrewManager; }
|
||||
}
|
||||
|
||||
public SinglePlayerMode(GameModePreset preset, object param)
|
||||
: base(preset, param)
|
||||
{
|
||||
|
||||
CargoManager = new CargoManager();
|
||||
|
||||
endShiftButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 220, 20, 200, 25), "End shift", null, Alignment.TopLeft, Alignment.Center, "");
|
||||
endShiftButton.Font = GUI.SmallFont;
|
||||
endShiftButton.OnClicked = TryEndShift;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
JobPrefab jobPrefab = null;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
jobPrefab = JobPrefab.List.Find(jp => jp.Name == "Captain");
|
||||
break;
|
||||
case 1:
|
||||
jobPrefab = JobPrefab.List.Find(jp => jp.Name == "Engineer");
|
||||
break;
|
||||
case 2:
|
||||
jobPrefab = JobPrefab.List.Find(jp => jp.Name == "Mechanic");
|
||||
break;
|
||||
}
|
||||
|
||||
CharacterInfo characterInfo =
|
||||
new CharacterInfo(Character.HumanConfigFile, "", Gender.None, jobPrefab);
|
||||
CrewManager.characterInfos.Add(characterInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SinglePlayerMode(XElement element)
|
||||
: this(GameModePreset.list.Find(gm => gm.Name == "Single Player"), null)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "crew":
|
||||
GameMain.GameSession.CrewManager = new CrewManager(subElement);
|
||||
break;
|
||||
case "map":
|
||||
Map = Map.Load(subElement);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//backwards compatibility with older save files
|
||||
if (Map==null)
|
||||
{
|
||||
string mapSeed = ToolBox.GetAttributeString(element, "mapseed", "a");
|
||||
|
||||
GenerateMap(mapSeed);
|
||||
|
||||
Map.SetLocation(ToolBox.GetAttributeInt(element, "currentlocation", 0));
|
||||
}
|
||||
|
||||
savedOnStart = true;
|
||||
}
|
||||
|
||||
public void GenerateMap(string seed)
|
||||
{
|
||||
Map = new Map(seed, 500);
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
CargoManager.CreateItems();
|
||||
|
||||
if (!savedOnStart)
|
||||
{
|
||||
SaveUtil.SaveGame(GameMain.GameSession.SaveFile);
|
||||
savedOnStart = true;
|
||||
}
|
||||
|
||||
endTimer = 5.0f;
|
||||
|
||||
isRunning = true;
|
||||
|
||||
CrewManager.StartShift();
|
||||
}
|
||||
|
||||
public bool TryHireCharacter(HireManager hireManager, CharacterInfo characterInfo)
|
||||
{
|
||||
if (CrewManager.Money < characterInfo.Salary) return false;
|
||||
|
||||
hireManager.availableCharacters.Remove(characterInfo);
|
||||
CrewManager.characterInfos.Add(characterInfo);
|
||||
|
||||
CrewManager.Money -= characterInfo.Salary;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public string GetMoney()
|
||||
{
|
||||
return "Money: " + CrewManager.Money;
|
||||
}
|
||||
|
||||
|
||||
private Submarine GetLeavingSub()
|
||||
{
|
||||
if (Character.Controlled != null && Character.Controlled.Submarine != null)
|
||||
{
|
||||
if (Character.Controlled.Submarine.AtEndPosition || Character.Controlled.Submarine.AtStartPosition)
|
||||
{
|
||||
return Character.Controlled.Submarine;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Submarine closestSub = Submarine.FindClosest(GameMain.GameScreen.Cam.WorldViewCenter);
|
||||
if (closestSub != null && (closestSub.AtEndPosition || closestSub.AtStartPosition))
|
||||
{
|
||||
return closestSub.DockedTo.Contains(Submarine.MainSub) ? Submarine.MainSub : closestSub;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<Submarine> GetSubsToLeaveBehind(Submarine leavingSub)
|
||||
{
|
||||
//leave subs behind if they're not docked to the leaving sub and not at the same exit
|
||||
return Submarine.Loaded.FindAll(s =>
|
||||
s != leavingSub &&
|
||||
!leavingSub.DockedTo.Contains(s) &&
|
||||
(s.AtEndPosition != leavingSub.AtEndPosition || s.AtStartPosition != leavingSub.AtStartPosition));
|
||||
}
|
||||
|
||||
public override void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!isRunning|| GUI.DisableHUD) return;
|
||||
|
||||
CrewManager.Draw(spriteBatch);
|
||||
|
||||
if (Submarine.MainSub == null) return;
|
||||
|
||||
Submarine leavingSub = GetLeavingSub();
|
||||
|
||||
if (leavingSub == null)
|
||||
{
|
||||
endShiftButton.Visible = false;
|
||||
}
|
||||
else if (leavingSub.AtEndPosition)
|
||||
{
|
||||
endShiftButton.Text = ToolBox.LimitString("Enter " + Map.SelectedLocation.Name, endShiftButton.Font, endShiftButton.Rect.Width - 5);
|
||||
endShiftButton.UserData = leavingSub;
|
||||
endShiftButton.Visible = true;
|
||||
}
|
||||
else if (leavingSub.AtStartPosition)
|
||||
{
|
||||
endShiftButton.Text = ToolBox.LimitString("Enter " + Map.CurrentLocation.Name, endShiftButton.Font, endShiftButton.Rect.Width - 5);
|
||||
endShiftButton.UserData = leavingSub;
|
||||
endShiftButton.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
endShiftButton.Visible = false;
|
||||
}
|
||||
|
||||
endShiftButton.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
if (!isRunning) return;
|
||||
|
||||
base.AddToGUIUpdateList();
|
||||
|
||||
CrewManager.AddToGUIUpdateList();
|
||||
|
||||
endShiftButton.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (!isRunning || GUI.DisableHUD) return;
|
||||
|
||||
base.Update(deltaTime);
|
||||
|
||||
CrewManager.Update(deltaTime);
|
||||
|
||||
endShiftButton.Update(deltaTime);
|
||||
|
||||
if (!crewDead)
|
||||
{
|
||||
if (!CrewManager.characters.Any(c => !c.IsDead)) crewDead = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
endTimer -= deltaTime;
|
||||
|
||||
if (endTimer <= 0.0f) EndShift(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public override void End(string endMessage = "")
|
||||
{
|
||||
isRunning = false;
|
||||
|
||||
bool success = CrewManager.characters.Any(c => !c.IsDead);
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (subsToLeaveBehind == null || leavingSub == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Leaving submarine not selected -> selecting the closest one");
|
||||
|
||||
leavingSub = GetLeavingSub();
|
||||
|
||||
subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
|
||||
}
|
||||
}
|
||||
|
||||
GameMain.GameSession.EndShift("");
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (leavingSub != Submarine.MainSub && !leavingSub.DockedTo.Contains(Submarine.MainSub))
|
||||
{
|
||||
Submarine.MainSub = leavingSub;
|
||||
|
||||
GameMain.GameSession.Submarine = leavingSub;
|
||||
|
||||
foreach (Submarine sub in subsToLeaveBehind)
|
||||
{
|
||||
MapEntity.mapEntityList.RemoveAll(e => e.Submarine == sub && e is LinkedSubmarine);
|
||||
LinkedSubmarine.CreateDummy(leavingSub, sub);
|
||||
}
|
||||
}
|
||||
|
||||
if (atEndPosition)
|
||||
{
|
||||
Map.MoveToNextLocation();
|
||||
}
|
||||
|
||||
SaveUtil.SaveGame(GameMain.GameSession.SaveFile);
|
||||
}
|
||||
|
||||
|
||||
if (!success)
|
||||
{
|
||||
var summaryScreen = GUIMessageBox.VisibleBox;
|
||||
|
||||
if (summaryScreen != null)
|
||||
{
|
||||
summaryScreen = summaryScreen.children[0];
|
||||
summaryScreen.RemoveChild(summaryScreen.children.Find(c => c is GUIButton));
|
||||
|
||||
var okButton = new GUIButton(new Rectangle(-120, 0, 100, 30), "Load game", Alignment.BottomRight, "", summaryScreen);
|
||||
okButton.OnClicked += GameMain.GameSession.LoadPrevious;
|
||||
okButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return true; };
|
||||
|
||||
var quitButton = new GUIButton(new Rectangle(0, 0, 100, 30), "Quit", Alignment.BottomRight, "", summaryScreen);
|
||||
quitButton.OnClicked += GameMain.LobbyScreen.QuitToMainMenu;
|
||||
quitButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return true; };
|
||||
}
|
||||
}
|
||||
|
||||
CrewManager.EndShift();
|
||||
for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
Character.CharacterList[i].Remove();
|
||||
}
|
||||
|
||||
Submarine.Unload();
|
||||
}
|
||||
|
||||
private bool TryEndShift(GUIButton button, object obj)
|
||||
{
|
||||
leavingSub = obj as Submarine;
|
||||
if (leavingSub != null)
|
||||
{
|
||||
subsToLeaveBehind = GetSubsToLeaveBehind(leavingSub);
|
||||
}
|
||||
|
||||
atEndPosition = leavingSub.AtEndPosition;
|
||||
|
||||
if (subsToLeaveBehind.Any())
|
||||
{
|
||||
string msg = "";
|
||||
if (subsToLeaveBehind.Count == 1)
|
||||
{
|
||||
msg = "One of your vessels isn't at the exit yet. Do you want to leave it behind?";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = "Some of your vessels aren't at the exit yet. Do you want to leave them behind?";
|
||||
}
|
||||
|
||||
var msgBox = new GUIMessageBox("Warning", msg, new string[] {"Yes", "No"});
|
||||
msgBox.Buttons[0].OnClicked += EndShift;
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
msgBox.Buttons[0].UserData = Submarine.Loaded.FindAll(s => !subsToLeaveBehind.Contains(s));
|
||||
|
||||
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||
}
|
||||
else
|
||||
{
|
||||
EndShift(button, obj);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool EndShift(GUIButton button, object obj)
|
||||
{
|
||||
isRunning = false;
|
||||
|
||||
List<Submarine> leavingSubs = obj as List<Submarine>;
|
||||
if (leavingSubs == null) leavingSubs = new List<Submarine>() { GetLeavingSub() };
|
||||
|
||||
var cinematic = new TransitionCinematic(leavingSubs, GameMain.GameScreen.Cam, 5.0f);
|
||||
|
||||
SoundPlayer.OverrideMusicType = CrewManager.characters.Any(c => !c.IsDead) ? "endshift" : "crewdead";
|
||||
|
||||
CoroutineManager.StartCoroutine(EndCinematic(cinematic),"EndCinematic");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerable<object> EndCinematic(TransitionCinematic cinematic)
|
||||
{
|
||||
while (cinematic.Running)
|
||||
{
|
||||
if (Submarine.MainSub == null) yield return CoroutineStatus.Success;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (Submarine.MainSub == null) yield return CoroutineStatus.Success;
|
||||
|
||||
End("");
|
||||
|
||||
yield return new WaitForSeconds(18.0f);
|
||||
|
||||
SoundPlayer.OverrideMusicType = null;
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public void Save(XElement element)
|
||||
{
|
||||
//element.Add(new XAttribute("day", day));
|
||||
XElement modeElement = new XElement("gamemode");
|
||||
|
||||
//modeElement.Add(new XAttribute("currentlocation", Map.CurrentLocationIndex));
|
||||
//modeElement.Add(new XAttribute("mapseed", Map.Seed));
|
||||
|
||||
|
||||
CrewManager.Save(modeElement);
|
||||
Map.Save(modeElement);
|
||||
|
||||
element.Add(modeElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
using Barotrauma.Networking;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class TraitorManager
|
||||
{
|
||||
public Character TraitorCharacter
|
||||
{
|
||||
get { return traitorCharacter; }
|
||||
}
|
||||
|
||||
public Character TargetCharacter
|
||||
{
|
||||
get { return targetCharacter; }
|
||||
}
|
||||
|
||||
private Character traitorCharacter, targetCharacter;
|
||||
|
||||
public TraitorManager(GameServer server)
|
||||
{
|
||||
Start(server);
|
||||
}
|
||||
|
||||
private void Start(GameServer server)
|
||||
{
|
||||
if (server == null) return;
|
||||
|
||||
List<Character> characters = new List<Character>();
|
||||
foreach (Client client in server.ConnectedClients)
|
||||
{
|
||||
if (client.Character != null)
|
||||
characters.Add(client.Character);
|
||||
}
|
||||
|
||||
if (server.Character!= null) characters.Add(server.Character);
|
||||
|
||||
if (characters.Count < 2)
|
||||
{
|
||||
traitorCharacter = null;
|
||||
targetCharacter = null;
|
||||
return;
|
||||
}
|
||||
|
||||
int traitorIndex = Rand.Range(0, characters.Count);
|
||||
|
||||
int targetIndex = Rand.Range(0, characters.Count);
|
||||
while (targetIndex == traitorIndex)
|
||||
{
|
||||
targetIndex = Rand.Range(0, characters.Count);
|
||||
}
|
||||
|
||||
traitorCharacter = characters[traitorIndex];
|
||||
targetCharacter = characters[targetIndex];
|
||||
|
||||
if (server.Character == null)
|
||||
{
|
||||
new GUIMessageBox("New traitor", traitorCharacter.Name + " is the traitor and the target is " + targetCharacter.Name+".");
|
||||
}
|
||||
else if (server.Character == traitorCharacter)
|
||||
{
|
||||
CreateStartPopUp(traitorCharacter.Name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static void CreateStartPopUp(string targetName)
|
||||
{
|
||||
new GUIMessageBox("You are the Traitor!",
|
||||
"Your secret task is to assassinate " + targetName + "! Discretion is an utmost concern; sinking the submarine and killing the entire crew "
|
||||
+ "will arouse suspicion amongst the Fleet. If possible, make the death look like an accident.", 400, 350);
|
||||
}
|
||||
|
||||
public string GetEndMessage()
|
||||
{
|
||||
if (GameMain.Server == null || traitorCharacter == null || targetCharacter == null) return "";
|
||||
|
||||
string endMessage = "";
|
||||
|
||||
if (targetCharacter.IsDead && !traitorCharacter.IsDead)
|
||||
{
|
||||
endMessage = traitorCharacter.Name + " was a traitor! ";
|
||||
endMessage += (traitorCharacter.Info.Gender == Gender.Male) ? "His" : "Her";
|
||||
endMessage += " task was to assassinate " + targetCharacter.Name + ". The task was successful.";
|
||||
}
|
||||
else if (targetCharacter.IsDead && traitorCharacter.IsDead)
|
||||
{
|
||||
endMessage = traitorCharacter.Name + " was a traitor! ";
|
||||
endMessage += (traitorCharacter.Info.Gender == Gender.Male) ? "His" : "Her";
|
||||
endMessage += " task was to assassinate " + targetCharacter.Name + ". The task was successful, but luckily the bastard didn't make it out alive either.";
|
||||
}
|
||||
else if (traitorCharacter.IsDead)
|
||||
{
|
||||
endMessage = traitorCharacter.Name + " was a traitor! ";
|
||||
endMessage += (traitorCharacter.Info.Gender == Gender.Male) ? "His" : "Her";
|
||||
endMessage += " task was to assassinate " + targetCharacter.Name + ", but ";
|
||||
endMessage += (traitorCharacter.Info.Gender == Gender.Male) ? "he" : "she";
|
||||
endMessage += " got " + ((traitorCharacter.Info.Gender == Gender.Male) ? "himself" : "herself");
|
||||
endMessage += " killed before completing it.";
|
||||
}
|
||||
else
|
||||
{
|
||||
endMessage = traitorCharacter.Name + " was a traitor! ";
|
||||
endMessage += (traitorCharacter.Info.Gender == Gender.Male) ? "His" : "Her";
|
||||
endMessage += " task was to assassinate " + targetCharacter.Name + ". ";
|
||||
endMessage += (Submarine.MainSub.AtEndPosition) ?
|
||||
"The task was unsuccessful - the submarine has reached its destination." :
|
||||
"The task was unsuccessful.";
|
||||
}
|
||||
|
||||
return endMessage;
|
||||
}
|
||||
|
||||
//public void CharacterLeft(Character character)
|
||||
//{
|
||||
// if (character != traitorCharacter && character != targetCharacter) return;
|
||||
|
||||
// if (character == traitorCharacter)
|
||||
// {
|
||||
// string endMessage = "The traitor has disconnected from the server.";
|
||||
// End(endMessage);
|
||||
// }
|
||||
// else if (character == targetCharacter)
|
||||
// {
|
||||
// string endMessage = "The traitor's target has disconnected from the server.";
|
||||
// End(endMessage);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,674 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class BasicTutorial : TutorialType
|
||||
{
|
||||
public BasicTutorial(string name)
|
||||
:base (name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override IEnumerable<object> UpdateState()
|
||||
{
|
||||
//spawn some fish next to the player
|
||||
GameMain.GameScreen.BackgroundCreatureManager.SpawnSprites(2,
|
||||
Submarine.MainSub.Position + Character.Controlled.Position);
|
||||
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
var wire = item.GetComponent<Wire>();
|
||||
if (wire != null && wire.Connections.Any(c => c != null))
|
||||
{
|
||||
wire.Locked = true;
|
||||
}
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(4.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("Use WASD to move and the 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<Door>();
|
||||
|
||||
while (!tutorialDoor.IsOpen && Character.Controlled.WorldPosition.X < tutorialDoor.Item.WorldPosition.X)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
infoBox = CreateInfoFrame("Hold W or S to walk up or down stairs. Use shift to run.", true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
infoBox = CreateInfoFrame("At the moment the submarine has no power, which means that crucial systems such as the oxygen generator or the engine aren't running. Let's fix this: 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<Reactor>();
|
||||
reactor.MeltDownTemp = 20000.0f;
|
||||
|
||||
while (Vector2.Distance(Character.Controlled.Position, reactor.Item.Position) > 200.0f)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("The reactor requires fuel rods to generate power. You can grab one from the steel cabinet by walking next to it and pressing E.");
|
||||
|
||||
while (Character.Controlled.SelectedConstruction == null || Character.Controlled.SelectedConstruction.Name != "Steel Cabinet")
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Pick up one of the fuel rods either by double-clicking or dragging and dropping it into your inventory.");
|
||||
|
||||
while (!HasItem("Fuel Rod"))
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Select the reactor by walking next to it and pressing E.");
|
||||
|
||||
while (Character.Controlled.SelectedConstruction != reactor.Item)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("Load the fuel rod into the reactor by dropping it into any of the 5 slots.");
|
||||
|
||||
while (reactor.AvailableFuel <= 0.0f)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("The reactor is now fueled up. Try turning it on by increasing the fission rate.");
|
||||
|
||||
while (reactor.FissionRate <= 0.0f)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("The reactor core has started generating heat, which in turn generates power for the submarine. The power generation is very low at the moment,"
|
||||
+ " because the reactor is set to shut itself down when the temperature rises above 500 degrees Celsius. You can adjust the temperature limit by changing the \"Shutdown Temperature\" in the control panel.", true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
reactor.ShutDownTemp = Math.Min(reactor.ShutDownTemp, 5000.0f);
|
||||
yield return CoroutineStatus.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 isn't enough power, devices won't function properly (or at all), and if there's too much power, some devices may be damaged."
|
||||
+ " Try to raise the temperature of the reactor close to 3000 degrees by adjusting the fission and cooling rates.", true);
|
||||
|
||||
while (Math.Abs(reactor.Temperature - 3000.0f) > 100.0f)
|
||||
{
|
||||
reactor.AutoTemp = false;
|
||||
reactor.ShutDownTemp = Math.Min(reactor.ShutDownTemp, 5000.0f);
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("Looks like we're up and running! Now you should turn on the \"Automatic temperature control\", which will make the reactor "
|
||||
+ "automatically adjust the temperature to a suitable level. Even though it's an easy way to keep the reactor up and running most of the time, "
|
||||
+ "you should keep in mind that it changes the temperature very slowly and carefully, which may cause issues if there are sudden changes in grid load.");
|
||||
|
||||
while (!reactor.AutoTemp)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("That's the basics of operating the reactor! Now that there's power available for the engines, it's time to get the submarine moving. "
|
||||
+ "Deselect the reactor by pressing E and head to the command room at the right edge of the vessel.");
|
||||
|
||||
Steering steering = Item.ItemList.Find(i => i.HasTag("tutorialsteering")).GetComponent<Steering>();
|
||||
Radar radar = steering.Item.GetComponent<Radar>();
|
||||
|
||||
while (Vector2.Distance(Character.Controlled.Position, steering.Item.Position) > 150.0f)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(KeepReactorRunning(reactor));
|
||||
|
||||
infoBox = CreateInfoFrame("Select the navigation terminal by walking next to it and pressing E.");
|
||||
|
||||
while (Character.Controlled.SelectedConstruction != steering.Item)
|
||||
{
|
||||
yield return CoroutineStatus.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 CoroutineStatus.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 use it on the terminal by left clicking.");
|
||||
|
||||
while (Character.Controlled.SelectedConstruction != steering.Item ||
|
||||
Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.Name == "Screwdriver") == null)
|
||||
{
|
||||
yield return CoroutineStatus.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 (!HasItem("Wire"))
|
||||
{
|
||||
yield return CoroutineStatus.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<PowerTransfer>();
|
||||
|
||||
while ((Character.Controlled.SelectedConstruction != junctionBox.Item &&
|
||||
Character.Controlled.SelectedConstruction != steering.Item) ||
|
||||
Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.Name == "Screwdriver") == null)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (Character.Controlled.SelectedItems.FirstOrDefault(i => i != null && i.GetComponent<Wire>() != 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<Wire>() != null) == null)
|
||||
{
|
||||
yield return CoroutineStatus.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"));
|
||||
|
||||
while (steeringConnection.Wires.FirstOrDefault(w => w != null) == null)
|
||||
{
|
||||
yield return CoroutineStatus.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 CoroutineStatus.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 if you don't care for neatly laid out wiring, you can just "
|
||||
+ "run it straight to the junction box.");
|
||||
|
||||
while (Character.Controlled.SelectedConstruction == null || Character.Controlled.SelectedConstruction.GetComponent<PowerTransfer>() == null)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Connect the wire to the junction box by pulling it to the power connection, the same way you did with the navigation terminal.");
|
||||
|
||||
while (radar.Voltage < 0.1f)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Great! Now we should be able to get moving.");
|
||||
|
||||
|
||||
while (Character.Controlled.SelectedConstruction != steering.Item)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("You can take a look at the area around the sub by selecting the \"Sonar\" checkbox.");
|
||||
|
||||
while (!radar.IsActive)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("The green rectangle in the middle is the submarine, and the flickering shapes outside it are the walls of an underwater cavern. "
|
||||
+ "Try moving the submarine by clicking somewhere on the monitor and dragging the pointer to the direction you want to go to.");
|
||||
|
||||
while (steering.TargetVelocity == Vector2.Zero && steering.TargetVelocity.Length() < 50.0f)
|
||||
{
|
||||
yield return CoroutineStatus.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.", true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Steer the submarine downwards, heading further into the cavern.");
|
||||
|
||||
while (Submarine.MainSub.WorldPosition.Y > 40000.0f)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
var moloch = Character.Create(
|
||||
"Content/Characters/Moloch/moloch.xml",
|
||||
steering.Item.WorldPosition + new Vector2(3000.0f, -500.0f));
|
||||
|
||||
moloch.PlaySound(CharacterSound.SoundType.Attack);
|
||||
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("Uh-oh... Something enormous just appeared on the radar.");
|
||||
|
||||
List<Structure> windows = new List<Structure>();
|
||||
foreach (Structure s in Structure.WallList)
|
||||
{
|
||||
if (s.CastShadow || !s.HasBody) continue;
|
||||
|
||||
if (s.Rect.Right > steering.Item.CurrentHull.Rect.Right) windows.Add(s);
|
||||
}
|
||||
|
||||
float slowdownTimer = 1.0f;
|
||||
bool broken = false;
|
||||
do
|
||||
{
|
||||
steering.TargetVelocity = Vector2.Zero;
|
||||
|
||||
slowdownTimer = Math.Max(0.0f, slowdownTimer - CoroutineManager.DeltaTime*0.3f);
|
||||
Submarine.MainSub.Velocity *= slowdownTimer;
|
||||
|
||||
moloch.AIController.SelectTarget(steering.Item.CurrentHull.AiTarget);
|
||||
Vector2 steeringDir = windows[0].WorldPosition - moloch.WorldPosition;
|
||||
if (steeringDir != Vector2.Zero) steeringDir = Vector2.Normalize(steeringDir);
|
||||
|
||||
moloch.AIController.SteeringManager.SteeringManual(CoroutineManager.DeltaTime, steeringDir*100.0f);
|
||||
|
||||
foreach (Structure window in windows)
|
||||
{
|
||||
for (int i = 0; i < window.SectionCount; i++)
|
||||
{
|
||||
if (!window.SectionIsLeaking(i)) continue;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
if (broken) break;
|
||||
}
|
||||
if (broken) break;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (!broken);
|
||||
|
||||
//fix everything except the command windows
|
||||
foreach (Structure w in Structure.WallList)
|
||||
{
|
||||
bool isWindow = windows.Contains(w);
|
||||
|
||||
for (int i = 0; i < w.SectionCount; i++)
|
||||
{
|
||||
if (!w.SectionIsLeaking(i)) continue;
|
||||
|
||||
if (isWindow)
|
||||
{
|
||||
//decrease window damage to slow down the leaking
|
||||
w.AddDamage(i, -w.SectionDamage(i) * 0.48f);
|
||||
}
|
||||
else
|
||||
{
|
||||
w.AddDamage(i, -100000.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Submarine.MainSub.GodMode = true;
|
||||
|
||||
var capacitor1 = Item.ItemList.Find(i => i.HasTag("capacitor1")).GetComponent<PowerContainer>();
|
||||
var capacitor2 = Item.ItemList.Find(i => i.HasTag("capacitor1")).GetComponent<PowerContainer>();
|
||||
CoroutineManager.StartCoroutine(KeepEnemyAway(moloch, new PowerContainer[] { capacitor1, capacitor2 }));
|
||||
|
||||
infoBox = CreateInfoFrame("The hull has been breached! Close all the doors to the command room to stop the water from flooding the entire sub!");
|
||||
|
||||
Door commandDoor1 = Item.ItemList.Find(i => i.HasTag("commanddoor1")).GetComponent<Door>();
|
||||
Door commandDoor2 = Item.ItemList.Find(i => i.HasTag("commanddoor2")).GetComponent<Door>();
|
||||
Door commandDoor3 = Item.ItemList.Find(i => i.HasTag("commanddoor3")).GetComponent<Door>();
|
||||
|
||||
//wait until the player is out of the room and the doors are closed
|
||||
while (Character.Controlled.WorldPosition.X > commandDoor1.Item.WorldPosition.X ||
|
||||
(commandDoor1.IsOpen || (commandDoor2.IsOpen || commandDoor3.IsOpen)))
|
||||
{
|
||||
//prevent the hull from filling up completely and crushing the player
|
||||
steering.Item.CurrentHull.Volume = Math.Min(steering.Item.CurrentHull.Volume, steering.Item.CurrentHull.FullVolume * 0.9f);
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
infoBox = CreateInfoFrame("You should quickly find yourself a diving mask or a diving suit. " +
|
||||
"There are some in the room next to the airlock.");
|
||||
|
||||
bool divingMaskSelected = false;
|
||||
|
||||
while (!HasItem("Diving Mask") && !HasItem("Diving Suit"))
|
||||
{
|
||||
if (!divingMaskSelected &&
|
||||
Character.Controlled.ClosestItem != null && Character.Controlled.ClosestItem.Name == "Diving Suit")
|
||||
{
|
||||
infoBox = CreateInfoFrame("There can only be one item in each inventory slot, so you need to take off "
|
||||
+ "the jumpsuit if you wish to wear a diving suit.");
|
||||
|
||||
divingMaskSelected = true;
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (HasItem("Diving Mask"))
|
||||
{
|
||||
infoBox = CreateInfoFrame("The diving mask will let you breathe underwater, but it won't protect from the water pressure outside the sub. " +
|
||||
"It should be fine for the situation at hand, but you still need to find an oxygen tank and drag it into the same slot as the mask." +
|
||||
"You should grab one or two from one of the cabinets.");
|
||||
}
|
||||
else if (HasItem("Diving Suit"))
|
||||
{
|
||||
infoBox = CreateInfoFrame("In addition to letting you breathe underwater, the suit will protect you from the water pressure outside the sub " +
|
||||
"(unlike the diving mask). However, you still need to drag an oxygen tank into the same slot as the suit to supply oxygen. " +
|
||||
"You should grab one or two from one of the cabinets.");
|
||||
}
|
||||
|
||||
while (!HasItem("Oxygen Tank"))
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("Now you should stop the creature attacking the submarine before it does any more damage. Head to the railgun room at the upper right corner of the sub.");
|
||||
|
||||
var railGun = Item.ItemList.Find(i => i.GetComponent<Turret>() != null);
|
||||
|
||||
while (Vector2.Distance(Character.Controlled.Position, railGun.Position) > 500)
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("The railgun requires a large power surge to fire. The reactor can't provide a surge large enough, so we need to use the "
|
||||
+ " supercapacitors in the railgun room. The capacitors need to be charged first; select them and crank up the recharge rate.");
|
||||
|
||||
while (capacitor1.RechargeSpeed < 0.5f && capacitor2.RechargeSpeed < 0.5f)
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("The capacitors take some time to recharge, so now is a good " +
|
||||
"time to head to the room below and load some shells for the railgun.");
|
||||
|
||||
|
||||
var loader = Item.ItemList.Find(i => i.Name == "Railgun Loader").GetComponent<ItemContainer>();
|
||||
|
||||
while (Math.Abs(Character.Controlled.Position.Y - loader.Item.Position.Y) > 80)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Grab one of the shells. You can load it by selecting the railgun loader and dragging the shell to. "
|
||||
+ "one of the free slots. You need two hands to carry a shell, so make sure you don't have anything else in either hand.");
|
||||
|
||||
while (loader.Item.ContainedItems.FirstOrDefault(i => i != null && i.Name == "Railgun Shell") == null)
|
||||
{
|
||||
moloch.Health = 50.0f;
|
||||
|
||||
capacitor1.Charge += 5.0f;
|
||||
capacitor2.Charge += 5.0f;
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Now we're ready to shoot! Select the railgun controller.");
|
||||
|
||||
while (Character.Controlled.SelectedConstruction == null || Character.Controlled.SelectedConstruction.Name != "Railgun Controller")
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
moloch.AnimController.SetPosition(ConvertUnits.ToSimUnits(Character.Controlled.WorldPosition + Vector2.UnitY * 600.0f));
|
||||
|
||||
infoBox = CreateInfoFrame("Use the right mouse button to aim and wait for the creature to come closer. When you're ready to shoot, "
|
||||
+ "press the left mouse button.");
|
||||
|
||||
while (!moloch.IsDead)
|
||||
{
|
||||
if (moloch.WorldPosition.Y > Character.Controlled.WorldPosition.Y + 600.0f)
|
||||
{
|
||||
moloch.AIController.SteeringManager.SteeringManual(CoroutineManager.DeltaTime, Character.Controlled.WorldPosition - moloch.WorldPosition);
|
||||
}
|
||||
|
||||
moloch.AIController.SelectTarget(Character.Controlled.AiTarget);
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
Submarine.MainSub.GodMode = false;
|
||||
|
||||
infoBox = CreateInfoFrame("The creature has died. Now you should fix the damages in the control room: " +
|
||||
"Grab a welding tool from the closet in the railgun room.");
|
||||
|
||||
while (!HasItem("Welding Tool"))
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("The welding tool requires fuel to work. Grab a welding fuel tank and attach it to the tool " +
|
||||
"by dragging it into the same slot.");
|
||||
|
||||
do
|
||||
{
|
||||
var weldingTool = Character.Controlled.Inventory.Items.FirstOrDefault(i => i != null && i.Name == "Welding Tool");
|
||||
if (weldingTool != null &&
|
||||
weldingTool.ContainedItems.FirstOrDefault(contained => contained != null && contained.Name == "Welding Fuel Tank") != null) break;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (true);
|
||||
|
||||
|
||||
infoBox = CreateInfoFrame("You can aim with the tool using the right mouse button and weld using the left button. " +
|
||||
"Head to the command room to fix the leaks there.");
|
||||
|
||||
do
|
||||
{
|
||||
broken = false;
|
||||
foreach (Structure window in windows)
|
||||
{
|
||||
for (int i = 0; i < window.SectionCount; i++)
|
||||
{
|
||||
if (!window.SectionIsLeaking(i)) continue;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
if (broken) break;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
} while (broken);
|
||||
|
||||
infoBox = CreateInfoFrame("The hull is fixed now, but there's still quite a bit of water inside the sub. It should be pumped out "
|
||||
+ "using the bilge pump in the room at the bottom of the submarine.");
|
||||
|
||||
Pump pump = Item.ItemList.Find(i => i.HasTag("tutorialpump")).GetComponent<Pump>();
|
||||
|
||||
while (Vector2.Distance(Character.Controlled.Position, pump.Item.Position) > 100.0f)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("The two pumps inside the ballast tanks "
|
||||
+ "are connected straight to the navigation terminal and can't be manually controlled unless you mess with their wiring, " +
|
||||
"so you should only use the pump in the middle room to pump out the water. Select it, turn it on and adjust the pumping speed " +
|
||||
"to start pumping water out.", true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
bool brokenMsgShown = false;
|
||||
|
||||
Item brokenBox = null;
|
||||
|
||||
while (pump.FlowPercentage > 0.0f || pump.CurrFlow <= 0.0f || !pump.IsActive)
|
||||
{
|
||||
if (!brokenMsgShown && pump.Voltage < pump.MinVoltage && Character.Controlled.SelectedConstruction == pump.Item)
|
||||
{
|
||||
brokenMsgShown = true;
|
||||
|
||||
infoBox = CreateInfoFrame("Looks like the pump isn't getting any power. The water must have short-circuited some of the junction "
|
||||
+"boxes. You can check which boxes are broken by selecting them.");
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (Character.Controlled.SelectedConstruction!=null &&
|
||||
Character.Controlled.SelectedConstruction.GetComponent<PowerTransfer>() != null &&
|
||||
Character.Controlled.SelectedConstruction.Condition == 0.0f)
|
||||
{
|
||||
brokenBox = Character.Controlled.SelectedConstruction;
|
||||
|
||||
infoBox = CreateInfoFrame("Here's our problem: this junction box is broken. Luckily engineers are adept at fixing electrical devices - "
|
||||
+"you just need to find a spare wire and click the \"Fix\"-button to repair the box.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (pump.Voltage > pump.MinVoltage) break;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
}
|
||||
|
||||
if (brokenBox != null && brokenBox.Condition > 50.0f && pump.Voltage < pump.MinVoltage)
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
if (pump.Voltage < pump.MinVoltage)
|
||||
{
|
||||
infoBox = CreateInfoFrame("The pump is still not running. Check if there are more broken junction boxes between the pump and the reactor.");
|
||||
}
|
||||
brokenBox = null;
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("The pump is up and running. Wait for the water to be drained out.");
|
||||
|
||||
while (pump.Item.CurrentHull.Volume > 1000.0f)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("That was all there is to this tutorial! Now you should be able to handle " +
|
||||
"most of the basic tasks on board the submarine.");
|
||||
|
||||
yield return new WaitForSeconds(4.0f);
|
||||
|
||||
Character.Controlled = null;
|
||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
|
||||
var cinematic = new TransitionCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, 5.0f);
|
||||
|
||||
while (cinematic.Running)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
Submarine.Unload();
|
||||
GameMain.MainMenuScreen.Select();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private bool HasItem(string itemName)
|
||||
{
|
||||
if (Character.Controlled == null) return false;
|
||||
|
||||
return Character.Controlled.Inventory.FindItem(itemName) != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected IEnumerable<object> KeepReactorRunning(Reactor reactor)
|
||||
{
|
||||
do
|
||||
{
|
||||
reactor.AutoTemp = true;
|
||||
reactor.ShutDownTemp = 5000.0f;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (Item.ItemList.Contains(reactor.Item));
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// keeps the enemy away from the sub until the capacitors are loaded
|
||||
/// </summary>
|
||||
private IEnumerable<object> KeepEnemyAway(Character enemy, PowerContainer[] capacitors)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (enemy == null || Character.Controlled == null) break;
|
||||
|
||||
enemy.Health = 50.0f;
|
||||
|
||||
enemy.AIController.State = AIController.AiState.None;
|
||||
|
||||
Vector2 targetPos = Character.Controlled.WorldPosition + new Vector2(0.0f, 3000.0f);
|
||||
|
||||
Vector2 steering = targetPos - enemy.WorldPosition;
|
||||
if (steering != Vector2.Zero) steering = Vector2.Normalize(steering);
|
||||
|
||||
enemy.AIController.Steering = steering * 2.0f;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (capacitors.FirstOrDefault(c => c.Charge > 0.4f) == null);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class EditorTutorial : TutorialType
|
||||
{
|
||||
public EditorTutorial(string name)
|
||||
: base (name)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<object> UpdateState()
|
||||
{
|
||||
infoBox = CreateInfoFrame("Use the mouse wheel to zoom in and out, and WASD to move the camera around.", true);
|
||||
|
||||
while (infoBox!=null)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Press \"Structure\" at the left side of the screen to start placing some walls.");
|
||||
|
||||
while (GameMain.EditMapScreen.SelectedTab != (int)MapEntityCategory.Structure)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Select \"topwall\" from the list.", true);
|
||||
|
||||
while (MapEntityPrefab.Selected == null || MapEntityPrefab.Selected.Name != "topwall")
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("You can now create a horizontal wall by clicking and dragging. When you're done, right click to stop creating walls.");
|
||||
|
||||
|
||||
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Barotrauma.Tutorials;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class TutorialMode : GameMode
|
||||
{
|
||||
public TutorialType tutorialType;
|
||||
|
||||
public static void StartTutorial(TutorialType tutorialType)
|
||||
{
|
||||
Submarine.MainSub = Submarine.Load("Content/Map/TutorialSub.sub", "", true);
|
||||
|
||||
tutorialType.Initialize();
|
||||
}
|
||||
|
||||
public TutorialMode(GameModePreset preset, object param)
|
||||
: base(preset, param)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
tutorialType.Start();
|
||||
|
||||
}
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
tutorialType.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
tutorialType.Update(deltaTime);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public override void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
base.Draw(spriteBatch);
|
||||
|
||||
//CrewManager.Draw(spriteBatch);
|
||||
tutorialType.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class TutorialType
|
||||
{
|
||||
|
||||
public static List<TutorialType> TutorialTypes;
|
||||
|
||||
protected GUIComponent infoBox;
|
||||
|
||||
Character character;
|
||||
|
||||
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
static TutorialType()
|
||||
{
|
||||
TutorialTypes = new List<TutorialType>();
|
||||
|
||||
TutorialTypes.Add(new BasicTutorial("Basic tutorial"));
|
||||
|
||||
}
|
||||
|
||||
public TutorialType(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
|
||||
public virtual void Initialize()
|
||||
{
|
||||
|
||||
GameMain.GameSession = new GameSession(Submarine.MainSub, "", GameModePreset.list.Find(gm => gm.Name.ToLowerInvariant() == "tutorial"));
|
||||
(GameMain.GameSession.gameMode as TutorialMode).tutorialType = this;
|
||||
|
||||
GameMain.GameSession.StartShift("tuto");
|
||||
|
||||
GameMain.GameSession.TaskManager.Tasks.Clear();
|
||||
|
||||
GameMain.GameScreen.Select();
|
||||
}
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
|
||||
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.Create(charInfo, wayPoint.WorldPosition, false, false);
|
||||
Character.Controlled = character;
|
||||
character.GiveJobItems(null);
|
||||
|
||||
var idCard = character.Inventory.FindItem("ID Card");
|
||||
if (idCard == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Item prefab \"ID Card\" not found!");
|
||||
return;
|
||||
}
|
||||
idCard.AddTag("com");
|
||||
idCard.AddTag("eng");
|
||||
|
||||
//CoroutineManager.StartCoroutine(QuitChecker());
|
||||
CoroutineManager.StartCoroutine(UpdateState());
|
||||
}
|
||||
|
||||
public virtual void AddToGUIUpdateList()
|
||||
{
|
||||
if (infoBox != null) infoBox.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public virtual void Update(float deltaTime)
|
||||
{
|
||||
if (character!=null)
|
||||
{
|
||||
if (Character.Controlled==null)
|
||||
{
|
||||
CoroutineManager.StopCoroutines("TutorialMode.UpdateState");
|
||||
infoBox = null;
|
||||
}
|
||||
else if (Character.Controlled.IsDead)
|
||||
{
|
||||
Character.Controlled = null;
|
||||
|
||||
CoroutineManager.StopCoroutines("TutorialMode.UpdateState");
|
||||
infoBox = null;
|
||||
CoroutineManager.StartCoroutine(Dead());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//CrewManager.Update(deltaTime);
|
||||
|
||||
if (infoBox != null) infoBox.Update(deltaTime);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<object> UpdateState()
|
||||
{
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public virtual void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
|
||||
if (infoBox != null) infoBox.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private IEnumerable<object> Dead()
|
||||
{
|
||||
yield return new WaitForSeconds(3.0f);
|
||||
|
||||
var messageBox = new GUIMessageBox("You have died", "Do you want to try again?", new string[] { "Yes", "No" });
|
||||
|
||||
messageBox.Buttons[0].OnClicked += Restart;
|
||||
messageBox.Buttons[0].OnClicked += messageBox.Close;
|
||||
|
||||
|
||||
messageBox.Buttons[1].OnClicked = GameMain.MainMenuScreen.SelectTab;
|
||||
messageBox.Buttons[1].OnClicked += messageBox.Close;
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
|
||||
protected bool CloseInfoFrame(GUIButton button, object userData)
|
||||
{
|
||||
infoBox = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected GUIComponent CreateInfoFrame(string text, bool hasButton = false)
|
||||
{
|
||||
int width = 300;
|
||||
int height = hasButton ? 110 : 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, "");
|
||||
//infoBlock.Color = infoBlock.Color * 0.8f;
|
||||
infoBlock.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
|
||||
infoBlock.Flash(Color.Green);
|
||||
|
||||
var textBlock = new GUITextBlock(new Rectangle(10, 10, width - 40, height), text, "", infoBlock, true);
|
||||
|
||||
if (hasButton)
|
||||
{
|
||||
var okButton = new GUIButton(new Rectangle(0, -40, 80, 25), "OK", Alignment.BottomCenter, "", textBlock);
|
||||
okButton.OnClicked = CloseInfoFrame;
|
||||
}
|
||||
|
||||
|
||||
GUI.PlayUISound(GUISoundType.Message);
|
||||
|
||||
return infoBlock;
|
||||
}
|
||||
|
||||
|
||||
private bool Restart(GUIButton button, object obj)
|
||||
{
|
||||
TutorialMode.StartTutorial(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class GameSession
|
||||
{
|
||||
public enum InfoFrameTab { Crew, Mission, ManagePlayers };
|
||||
|
||||
public readonly TaskManager TaskManager;
|
||||
|
||||
public readonly GameMode gameMode;
|
||||
|
||||
//two locations used as the start and end in the MP mode
|
||||
private Location[] dummyLocations;
|
||||
|
||||
private InfoFrameTab selectedTab;
|
||||
private GUIButton infoButton;
|
||||
private GUIFrame infoFrame;
|
||||
|
||||
private string saveFile;
|
||||
|
||||
private Submarine submarine;
|
||||
|
||||
public CrewManager CrewManager;
|
||||
|
||||
private ShiftSummary shiftSummary;
|
||||
|
||||
private Mission currentMission;
|
||||
|
||||
public Mission Mission
|
||||
{
|
||||
get
|
||||
{
|
||||
return currentMission;
|
||||
}
|
||||
}
|
||||
|
||||
private Level level;
|
||||
|
||||
public Level Level
|
||||
{
|
||||
get { return level; }
|
||||
}
|
||||
|
||||
public Map Map
|
||||
{
|
||||
get
|
||||
{
|
||||
SinglePlayerMode mode = (gameMode as SinglePlayerMode);
|
||||
return (mode == null) ? null : mode.Map;
|
||||
}
|
||||
}
|
||||
|
||||
public Location StartLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Map != null) return Map.CurrentLocation;
|
||||
|
||||
if (dummyLocations==null)
|
||||
{
|
||||
CreateDummyLocations();
|
||||
}
|
||||
|
||||
return dummyLocations[0];
|
||||
}
|
||||
}
|
||||
|
||||
public Location EndLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Map != null) return Map.SelectedLocation;
|
||||
|
||||
if (dummyLocations == null)
|
||||
{
|
||||
CreateDummyLocations();
|
||||
}
|
||||
|
||||
return dummyLocations[1];
|
||||
}
|
||||
}
|
||||
|
||||
public Submarine Submarine
|
||||
{
|
||||
get { return submarine; }
|
||||
set { submarine = value; }
|
||||
}
|
||||
|
||||
public string SaveFile
|
||||
{
|
||||
get { return saveFile; }
|
||||
}
|
||||
|
||||
public ShiftSummary ShiftSummary
|
||||
{
|
||||
get { return shiftSummary; }
|
||||
}
|
||||
|
||||
public GameSession(Submarine submarine, string saveFile, GameModePreset gameModePreset = null, string missionType="")
|
||||
{
|
||||
Submarine.MainSub = submarine;
|
||||
|
||||
GameMain.GameSession = this;
|
||||
|
||||
CrewManager = new CrewManager();
|
||||
|
||||
TaskManager = new TaskManager(this);
|
||||
|
||||
this.saveFile = saveFile;
|
||||
|
||||
infoButton = new GUIButton(new Rectangle(10, 10, 100, 20), "Info", "", null);
|
||||
infoButton.OnClicked = ToggleInfoFrame;
|
||||
|
||||
if (gameModePreset != null) gameMode = gameModePreset.Instantiate(missionType);
|
||||
this.submarine = submarine;
|
||||
}
|
||||
|
||||
public GameSession(Submarine selectedSub, string saveFile, XDocument doc)
|
||||
: this(selectedSub, saveFile)
|
||||
{
|
||||
Submarine.MainSub = submarine;
|
||||
|
||||
GameMain.GameSession = this;
|
||||
|
||||
CrewManager = new CrewManager();
|
||||
|
||||
selectedSub.Name = ToolBox.GetAttributeString(doc.Root, "submarine", selectedSub.Name);
|
||||
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "gamemode") continue;
|
||||
|
||||
gameMode = new SinglePlayerMode(subElement);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateDummyLocations()
|
||||
{
|
||||
dummyLocations = new Location[2];
|
||||
|
||||
string seed = "";
|
||||
if (GameMain.GameSession != null && GameMain.GameSession.Level != null)
|
||||
{
|
||||
seed = GameMain.GameSession.Level.Seed;
|
||||
}
|
||||
else if (GameMain.NetLobbyScreen != null)
|
||||
{
|
||||
seed = GameMain.NetLobbyScreen.LevelSeed;
|
||||
}
|
||||
|
||||
MTRandom rand = new MTRandom(ToolBox.StringToInt(seed));
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
dummyLocations[i] = Location.CreateRandom(new Vector2((float)rand.NextDouble() * 10000.0f, (float)rand.NextDouble() * 10000.0f));
|
||||
}
|
||||
}
|
||||
|
||||
public void StartShift(string levelSeed, bool loadSecondSub = false)
|
||||
{
|
||||
Level randomLevel = Level.CreateRandom(levelSeed);
|
||||
|
||||
StartShift(randomLevel, true, loadSecondSub);
|
||||
}
|
||||
|
||||
public void StartShift(Level level, bool reloadSub = true, bool loadSecondSub = false)
|
||||
{
|
||||
GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
|
||||
|
||||
this.level = level;
|
||||
|
||||
if (submarine==null)
|
||||
{
|
||||
DebugConsole.ThrowError("Couldn't start game session, submarine not selected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (reloadSub || Submarine.MainSub != submarine) submarine.Load(true);
|
||||
Submarine.MainSub = submarine;
|
||||
if (loadSecondSub)
|
||||
{
|
||||
if (Submarine.MainSubs[1] == null)
|
||||
{
|
||||
Submarine.MainSubs[1] = new Submarine(Submarine.MainSub.FilePath,Submarine.MainSub.MD5Hash.Hash,true);
|
||||
Submarine.MainSubs[1].Load(false);
|
||||
}
|
||||
else if (reloadSub)
|
||||
{
|
||||
Submarine.MainSubs[1].Load(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (level != null)
|
||||
{
|
||||
level.Generate();
|
||||
|
||||
submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
|
||||
|
||||
GameMain.GameScreen.BackgroundCreatureManager.SpawnSprites(80);
|
||||
}
|
||||
|
||||
if (gameMode.Mission != null)
|
||||
{
|
||||
currentMission = gameMode.Mission;
|
||||
}
|
||||
|
||||
shiftSummary = new ShiftSummary(this);
|
||||
|
||||
if (gameMode!=null) gameMode.Start();
|
||||
|
||||
if (gameMode.Mission != null) Mission.Start(Level.Loaded);
|
||||
|
||||
TaskManager.StartShift(level);
|
||||
|
||||
if (gameMode != null) gameMode.MsgBox();
|
||||
|
||||
Entity.Spawner = new EntitySpawner();
|
||||
|
||||
GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);
|
||||
SoundPlayer.SwitchMusic();
|
||||
}
|
||||
|
||||
public void EndShift(string endMessage)
|
||||
{
|
||||
if (Mission != null) Mission.End();
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
//CoroutineManager.StartCoroutine(GameMain.Server.EndGame(endMessage));
|
||||
|
||||
}
|
||||
else if (GameMain.Client == null)
|
||||
{
|
||||
//Submarine.Unload();
|
||||
GameMain.LobbyScreen.Select();
|
||||
}
|
||||
|
||||
if (shiftSummary != null)
|
||||
{
|
||||
GUIFrame summaryFrame = shiftSummary.CreateSummaryFrame(endMessage);
|
||||
GUIMessageBox.MessageBoxes.Add(summaryFrame);
|
||||
var okButton = new GUIButton(new Rectangle(0, 0, 100, 30), "Ok", Alignment.BottomRight, "", summaryFrame.children[0]);
|
||||
okButton.OnClicked = (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return true; };
|
||||
}
|
||||
|
||||
TaskManager.EndShift();
|
||||
|
||||
currentMission = null;
|
||||
|
||||
StatusEffect.StopAll();
|
||||
}
|
||||
|
||||
|
||||
public void KillCharacter(Character character)
|
||||
{
|
||||
CrewManager.KillCharacter(character);
|
||||
}
|
||||
|
||||
public void ReviveCharacter(Character character)
|
||||
{
|
||||
CrewManager.ReviveCharacter(character);
|
||||
}
|
||||
|
||||
public bool LoadPrevious(GUIButton button, object obj)
|
||||
{
|
||||
Submarine.Unload();
|
||||
|
||||
SaveUtil.LoadGame(saveFile);
|
||||
|
||||
GameMain.LobbyScreen.Select();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ToggleInfoFrame(GUIButton button, object obj)
|
||||
{
|
||||
if (infoFrame == null)
|
||||
{
|
||||
if (CrewManager != null && CrewManager.CrewCommander!= null && CrewManager.CrewCommander.IsOpen)
|
||||
{
|
||||
CrewManager.CrewCommander.ToggleGUIFrame();
|
||||
}
|
||||
|
||||
CreateInfoFrame();
|
||||
SelectInfoFrameTab(null, selectedTab);
|
||||
}
|
||||
else
|
||||
{
|
||||
infoFrame = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void CreateInfoFrame()
|
||||
{
|
||||
int width = 600, height = 400;
|
||||
|
||||
|
||||
infoFrame = new GUIFrame(
|
||||
Rectangle.Empty, Color.Black * 0.8f, null);
|
||||
|
||||
var innerFrame = new GUIFrame(
|
||||
new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), "", infoFrame);
|
||||
|
||||
innerFrame.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
|
||||
|
||||
var crewButton = new GUIButton(new Rectangle(0, -30, 100, 20), "Crew", "", innerFrame);
|
||||
crewButton.UserData = InfoFrameTab.Crew;
|
||||
crewButton.OnClicked = SelectInfoFrameTab;
|
||||
|
||||
var missionButton = new GUIButton(new Rectangle(100, -30, 100, 20), "Mission", "", innerFrame);
|
||||
missionButton.UserData = InfoFrameTab.Mission;
|
||||
missionButton.OnClicked = SelectInfoFrameTab;
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
var manageButton = new GUIButton(new Rectangle(200, -30, 130, 20), "Manage players", "", innerFrame);
|
||||
manageButton.UserData = InfoFrameTab.ManagePlayers;
|
||||
manageButton.OnClicked = SelectInfoFrameTab;
|
||||
}
|
||||
|
||||
var closeButton = new GUIButton(new Rectangle(0, 0, 80, 20), "Close", Alignment.BottomCenter, "", innerFrame);
|
||||
closeButton.OnClicked = ToggleInfoFrame;
|
||||
|
||||
}
|
||||
|
||||
private bool SelectInfoFrameTab(GUIButton button, object userData)
|
||||
{
|
||||
selectedTab = (InfoFrameTab)userData;
|
||||
|
||||
CreateInfoFrame();
|
||||
|
||||
switch (selectedTab)
|
||||
{
|
||||
case InfoFrameTab.Crew:
|
||||
CrewManager.CreateCrewFrame(CrewManager.characters, infoFrame.children[0] as GUIFrame);
|
||||
break;
|
||||
case InfoFrameTab.Mission:
|
||||
CreateMissionInfo(infoFrame.children[0] as GUIFrame);
|
||||
break;
|
||||
case InfoFrameTab.ManagePlayers:
|
||||
GameMain.Server.ManagePlayersFrame(infoFrame.children[0] as GUIFrame);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CreateMissionInfo(GUIFrame infoFrame)
|
||||
{
|
||||
if (Mission == null)
|
||||
{
|
||||
new GUITextBlock(new Rectangle(0,0,0,50), "No mission", "", infoFrame, true);
|
||||
return;
|
||||
}
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 40), Mission.Name, "", infoFrame, GUI.LargeFont);
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 50, 0, 20), "Reward: "+Mission.Reward, "", infoFrame, true);
|
||||
new GUITextBlock(new Rectangle(0, 70, 0, 50), Mission.Description, "", infoFrame, true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void AddToGUIUpdateList()
|
||||
{
|
||||
infoButton.AddToGUIUpdateList();
|
||||
|
||||
if (gameMode != null) gameMode.AddToGUIUpdateList();
|
||||
|
||||
if (infoFrame != null) infoFrame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
TaskManager.Update(deltaTime);
|
||||
|
||||
if (GUI.DisableHUD) return;
|
||||
|
||||
//guiRoot.Update(deltaTime);
|
||||
infoButton.Update(deltaTime);
|
||||
|
||||
if (gameMode != null) gameMode.Update(deltaTime);
|
||||
if (Mission != null) Mission.Update(deltaTime);
|
||||
if (infoFrame != null)
|
||||
{
|
||||
infoFrame.Update(deltaTime);
|
||||
|
||||
if (CrewManager != null && CrewManager.CrewCommander != null && CrewManager.CrewCommander.IsOpen)
|
||||
{
|
||||
infoFrame = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (GUI.DisableHUD) return;
|
||||
|
||||
infoButton.Draw(spriteBatch);
|
||||
|
||||
if (gameMode != null) gameMode.Draw(spriteBatch);
|
||||
if (infoFrame != null) infoFrame.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
public void Save(string filePath)
|
||||
{
|
||||
XDocument doc = new XDocument(
|
||||
new XElement("Gamesession"));
|
||||
|
||||
var now = DateTime.Now;
|
||||
doc.Root.Add(new XAttribute("savetime", now.ToShortTimeString() + ", " + now.ToShortDateString()));
|
||||
|
||||
doc.Root.Add(new XAttribute("submarine", submarine==null ? "" : submarine.Name));
|
||||
|
||||
doc.Root.Add(new XAttribute("mapseed", Map.Seed));
|
||||
|
||||
((SinglePlayerMode)gameMode).Save(doc.Root);
|
||||
|
||||
try
|
||||
{
|
||||
doc.Save(filePath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
DebugConsole.ThrowError("Saving gamesession to \"" + filePath + "\" failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class HireManager
|
||||
{
|
||||
public List<CharacterInfo> availableCharacters;
|
||||
|
||||
public const int MaxAvailableCharacters = 10;
|
||||
|
||||
public HireManager()
|
||||
{
|
||||
availableCharacters = new List<CharacterInfo>();
|
||||
}
|
||||
|
||||
public void GenerateCharacters(Location location, int amount)
|
||||
{
|
||||
for (int i = 0 ; i<amount ; i++)
|
||||
{
|
||||
JobPrefab job = location.Type.GetRandomHireable();
|
||||
if (job == null) return;
|
||||
|
||||
availableCharacters.Add(new CharacterInfo(Character.HumanConfigFile, "", Gender.None, job));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
static class InfoTextManager
|
||||
{
|
||||
|
||||
private static Dictionary<string, List<string>> infoTexts;
|
||||
|
||||
static InfoTextManager()
|
||||
{
|
||||
LoadInfoTexts(Path.Combine("Content", "InfoTexts.xml"));
|
||||
}
|
||||
|
||||
|
||||
private static void LoadInfoTexts(string file)
|
||||
{
|
||||
infoTexts = new Dictionary<string, List<string>>();
|
||||
|
||||
XDocument doc = ToolBox.TryLoadXml(file);
|
||||
if (doc == null || doc.Root == null) return;
|
||||
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
string infoName = subElement.Name.ToString().ToLowerInvariant();
|
||||
List<string> infoList = null;
|
||||
if (!infoTexts.TryGetValue(infoName, out infoList))
|
||||
{
|
||||
infoList = new List<string>();
|
||||
infoTexts.Add(infoName, infoList);
|
||||
}
|
||||
|
||||
infoList.Add(subElement.ElementInnerText());
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetInfoText(string infoName)
|
||||
{
|
||||
List<string> infoList = null;
|
||||
if (!infoTexts.TryGetValue(infoName.ToLowerInvariant(), out infoList) || !infoList.Any())
|
||||
{
|
||||
#if DEBUG
|
||||
return "Info text \"" + infoName + "\" not found";
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
string text = infoList[Rand.Int(infoList.Count)];
|
||||
|
||||
foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
|
||||
{
|
||||
text = text.Replace("[" + inputType.ToString() + "]", GameMain.Config.KeyBind(inputType).ToString());
|
||||
}
|
||||
|
||||
if (Submarine.MainSub != null) text = text.Replace("[sub]", Submarine.MainSub.Name);
|
||||
if (GameMain.GameSession != null && GameMain.GameSession.StartLocation != null)
|
||||
{
|
||||
text = text.Replace("[location]", GameMain.GameSession.StartLocation.Name);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class ShiftSummary
|
||||
{
|
||||
private Location startLocation, endLocation;
|
||||
|
||||
private GameSession gameSession;
|
||||
|
||||
private Mission selectedMission;
|
||||
|
||||
public ShiftSummary(GameSession gameSession)
|
||||
{
|
||||
this.gameSession = gameSession;
|
||||
|
||||
startLocation = gameSession.StartLocation;
|
||||
endLocation = gameSession.EndLocation;
|
||||
|
||||
selectedMission = gameSession.Mission;
|
||||
}
|
||||
|
||||
|
||||
public GUIFrame CreateSummaryFrame(string endMessage)
|
||||
{
|
||||
bool singleplayer = GameMain.NetworkMember == null;
|
||||
|
||||
bool gameOver = gameSession.CrewManager.characters.All(c => c.IsDead);
|
||||
bool progress = Submarine.MainSub.AtEndPosition;
|
||||
|
||||
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight), Color.Black * 0.8f);
|
||||
|
||||
int width = 760, height = 400;
|
||||
GUIFrame innerFrame = new GUIFrame(new Rectangle(0, 0, width, height), null, Alignment.Center, "", frame);
|
||||
|
||||
int y = 0;
|
||||
|
||||
if (singleplayer)
|
||||
{
|
||||
string summaryText = InfoTextManager.GetInfoText(gameOver ? "gameover" :
|
||||
(progress ? "progress" : "return"));
|
||||
|
||||
var infoText = new GUITextBlock(new Rectangle(0, y, 0, 50), summaryText, "", innerFrame, true);
|
||||
y += infoText.Rect.Height;
|
||||
}
|
||||
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(endMessage))
|
||||
{
|
||||
var endText = new GUITextBlock(new Rectangle(0, y, 0, 30), endMessage, "", innerFrame, true);
|
||||
|
||||
y += 30 + endText.Text.Split('\n').Length * 20;
|
||||
}
|
||||
|
||||
new GUITextBlock(new Rectangle(0, y, 0, 20), "Crew status:", "", innerFrame, GUI.LargeFont);
|
||||
y += 30;
|
||||
|
||||
GUIListBox listBox = new GUIListBox(new Rectangle(0,y,0,90), null, Alignment.TopLeft, "", innerFrame, true);
|
||||
|
||||
int x = 0;
|
||||
foreach (Character character in gameSession.CrewManager.characters)
|
||||
{
|
||||
if (GameMain.GameSession.Mission is CombatMission &&
|
||||
character.TeamID != GameMain.GameSession.CrewManager.WinningTeam)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var characterFrame = new GUIFrame(new Rectangle(x, y, 170, 70), Color.Transparent, "", listBox);
|
||||
characterFrame.OutlineColor = Color.Transparent;
|
||||
characterFrame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
characterFrame.CanBeFocused = false;
|
||||
|
||||
character.Info.CreateCharacterFrame(characterFrame,
|
||||
character.Info.Job != null ? (character.Info.Name + '\n' + "(" + character.Info.Job.Name + ")") : character.Info.Name, null);
|
||||
|
||||
string statusText = "OK";
|
||||
Color statusColor = Color.DarkGreen;
|
||||
|
||||
if (character.IsDead)
|
||||
{
|
||||
statusText = InfoTextManager.GetInfoText("CauseOfDeath." + character.CauseOfDeath.ToString());
|
||||
statusColor = Color.DarkRed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (character.IsUnconscious)
|
||||
{
|
||||
statusText = "Unconscious";
|
||||
statusColor = Color.DarkOrange;
|
||||
}
|
||||
else if (character.Health / character.MaxHealth < 0.8f)
|
||||
{
|
||||
statusText = "Injured";
|
||||
statusColor = Color.DarkOrange;
|
||||
}
|
||||
}
|
||||
|
||||
new GUITextBlock(
|
||||
new Rectangle(0, 0, 0, 20), statusText, statusColor * 0.8f, Color.White,
|
||||
Alignment.BottomLeft, Alignment.Center,
|
||||
null, characterFrame, true, GUI.SmallFont);
|
||||
|
||||
x += characterFrame.Rect.Width + 10;
|
||||
}
|
||||
|
||||
y += 120;
|
||||
|
||||
if (GameMain.GameSession.Mission != null)
|
||||
{
|
||||
new GUITextBlock(new Rectangle(0, y, 0, 20), "Mission: " + GameMain.GameSession.Mission.Name, "", innerFrame, GUI.LargeFont);
|
||||
y += 30;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, y, innerFrame.Rect.Width - 170, 0),
|
||||
(GameMain.GameSession.Mission.Completed) ? GameMain.GameSession.Mission.SuccessMessage : GameMain.GameSession.Mission.FailureMessage,
|
||||
"", innerFrame, true);
|
||||
|
||||
if (GameMain.GameSession.Mission.Completed && singleplayer)
|
||||
{
|
||||
new GUITextBlock(new Rectangle(0, 0, 0, 30), "Reward: " + GameMain.GameSession.Mission.Reward, "", Alignment.BottomLeft, Alignment.BottomLeft, innerFrame);
|
||||
}
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user