202 lines
7.6 KiB
C#
202 lines
7.6 KiB
C#
using Microsoft.Xna.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Xml.Linq;
|
|
|
|
namespace Barotrauma
|
|
{
|
|
abstract class CampaignMode : GameMode
|
|
{
|
|
public readonly CargoManager CargoManager;
|
|
|
|
public bool CheatsEnabled;
|
|
|
|
const int InitialMoney = 4700;
|
|
|
|
protected bool watchmenSpawned;
|
|
protected Character startWatchman, endWatchman;
|
|
|
|
//key = dialog flag, double = Timing.TotalTime when the line was last said
|
|
private Dictionary<string, double> dialogLastSpoken = new Dictionary<string, double>();
|
|
|
|
protected Map map;
|
|
public Map Map
|
|
{
|
|
get { return map; }
|
|
}
|
|
|
|
public override Mission Mission
|
|
{
|
|
get
|
|
{
|
|
return Map.CurrentLocation?.SelectedMission;
|
|
}
|
|
}
|
|
|
|
private int money;
|
|
public int Money
|
|
{
|
|
get { return money; }
|
|
set { money = Math.Max(value, 0); }
|
|
}
|
|
|
|
public CampaignMode(GameModePreset preset, object param)
|
|
: base(preset, param)
|
|
{
|
|
Money = InitialMoney;
|
|
CargoManager = new CargoManager(this);
|
|
}
|
|
|
|
public void GenerateMap(string seed)
|
|
{
|
|
map = new Map(seed);
|
|
}
|
|
|
|
protected 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 != Level.Loaded.StartOutpost && s != Level.Loaded.EndOutpost &&
|
|
(s.AtEndPosition != leavingSub.AtEndPosition || s.AtStartPosition != leavingSub.AtStartPosition));
|
|
}
|
|
|
|
public override void Start()
|
|
{
|
|
base.Start();
|
|
dialogLastSpoken.Clear();
|
|
watchmenSpawned = false;
|
|
startWatchman = null;
|
|
endWatchman = null;
|
|
}
|
|
|
|
public override void Update(float deltaTime)
|
|
{
|
|
base.Update(deltaTime);
|
|
|
|
if (!IsRunning) { return; }
|
|
#if CLIENT
|
|
if (GameMain.Client != null) { return; }
|
|
#endif
|
|
if (!watchmenSpawned)
|
|
{
|
|
if (Level.Loaded.StartOutpost != null) { startWatchman = SpawnWatchman(Level.Loaded.StartOutpost); }
|
|
if (Level.Loaded.EndOutpost != null) { endWatchman = SpawnWatchman(Level.Loaded.EndOutpost); }
|
|
watchmenSpawned = true;
|
|
#if SERVER
|
|
(this as MultiPlayerCampaign).LastUpdateID++;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
foreach (Character character in Character.CharacterList)
|
|
{
|
|
#if SERVER
|
|
if (string.IsNullOrEmpty(character.OwnerClientIP)) { continue; }
|
|
#else
|
|
if (!CrewManager.GetCharacters().Contains(character)) { continue; }
|
|
#endif
|
|
if (character.Submarine == Level.Loaded.StartOutpost && character.CurrentHull == startWatchman.CurrentHull)
|
|
{
|
|
CreateDialog(new List<Character> { startWatchman }, "EnterStartOutpost", 5 * 60.0f);
|
|
}
|
|
else if (character.Submarine == Level.Loaded.EndOutpost && character.CurrentHull == endWatchman.CurrentHull)
|
|
{
|
|
CreateDialog(new List<Character> { endWatchman }, "EnterEndOutpost", 5 * 60.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void CreateDialog(List<Character> speakers, string conversationTag, float minInterval)
|
|
{
|
|
if (dialogLastSpoken.TryGetValue(conversationTag, out double lastTime))
|
|
{
|
|
if (Timing.TotalTime - lastTime < minInterval) { return; }
|
|
}
|
|
|
|
CrewManager.AddConversation(
|
|
NPCConversation.CreateRandom(speakers, new List<string>() { conversationTag }));
|
|
dialogLastSpoken[conversationTag] = Timing.TotalTime;
|
|
}
|
|
|
|
private Character SpawnWatchman(Submarine outpost)
|
|
{
|
|
WayPoint watchmanSpawnpoint = WayPoint.WayPointList.Find(wp => wp.Submarine == outpost);
|
|
if (watchmanSpawnpoint == null)
|
|
{
|
|
DebugConsole.ThrowError("Failed to spawn a watchman at the outpost. No spawnpoints found inside the outpost.");
|
|
return null;
|
|
}
|
|
|
|
string seed = outpost == Level.Loaded.StartOutpost ? map.SelectedLocation.Name : map.CurrentLocation.Name;
|
|
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
|
|
|
|
JobPrefab watchmanJob = JobPrefab.List.Find(jp => jp.Identifier == "watchman");
|
|
CharacterInfo characterInfo = new CharacterInfo(Character.HumanConfigFile, jobPrefab: watchmanJob);
|
|
var spawnedCharacter = Character.Create(characterInfo, watchmanSpawnpoint.WorldPosition,
|
|
Level.Loaded.Seed + (outpost == Level.Loaded.StartOutpost ? "start" : "end"));
|
|
InitializeWatchman(spawnedCharacter);
|
|
(spawnedCharacter.AIController as HumanAIController)?.ObjectiveManager.SetOrder(
|
|
new AIObjectiveGoTo(watchmanSpawnpoint, spawnedCharacter, repeat: true, getDivingGearIfNeeded: false));
|
|
if (watchmanJob != null)
|
|
{
|
|
spawnedCharacter.GiveJobItems();
|
|
}
|
|
return spawnedCharacter;
|
|
}
|
|
|
|
protected void InitializeWatchman(Character character)
|
|
{
|
|
character.CharacterHealth.UseHealthWindow = false;
|
|
character.CharacterHealth.Unkillable = true;
|
|
character.CanInventoryBeAccessed = false;
|
|
character.CanBeDragged = false;
|
|
character.TeamID = Character.TeamType.FriendlyNPC;
|
|
character.SetCustomInteract(
|
|
WatchmanInteract,
|
|
hudText: TextManager.Get("TalkHint").Replace("[key]", GameMain.Config.KeyBind(InputType.Select).ToString()));
|
|
}
|
|
|
|
protected abstract void WatchmanInteract(Character watchman, Character interactor);
|
|
|
|
public abstract void Save(XElement element);
|
|
|
|
public void LogState()
|
|
{
|
|
DebugConsole.NewMessage("********* CAMPAIGN STATUS *********", Color.White);
|
|
DebugConsole.NewMessage(" Money: " + Money, Color.White);
|
|
DebugConsole.NewMessage(" Current location: " + map.CurrentLocation.Name, Color.White);
|
|
|
|
DebugConsole.NewMessage(" Available destinations: ", Color.White);
|
|
for (int i = 0; i < map.CurrentLocation.Connections.Count; i++)
|
|
{
|
|
Location destination = map.CurrentLocation.Connections[i].OtherLocation(map.CurrentLocation);
|
|
if (destination == map.SelectedLocation)
|
|
{
|
|
DebugConsole.NewMessage(" " + i + ". " + destination.Name + " [SELECTED]", Color.White);
|
|
}
|
|
else
|
|
{
|
|
DebugConsole.NewMessage(" " + i + ". " + destination.Name, Color.White);
|
|
}
|
|
}
|
|
|
|
if (map.CurrentLocation?.SelectedMission != null)
|
|
{
|
|
DebugConsole.NewMessage(" Selected mission: " + map.CurrentLocation.SelectedMission.Name, Color.White);
|
|
DebugConsole.NewMessage("\n" + map.CurrentLocation.SelectedMission.Description, Color.White);
|
|
}
|
|
}
|
|
|
|
public override void Remove()
|
|
{
|
|
base.Remove();
|
|
map?.Remove();
|
|
map = null;
|
|
}
|
|
}
|
|
}
|