Further separation of client-specific code
Still not done here, just gonna push a commit now so I can pull this from elsewhere.
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Particles;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if CLIENT
|
||||
using Barotrauma.Particles;
|
||||
#endif
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -49,9 +50,11 @@ namespace Barotrauma
|
||||
|
||||
public readonly float TargetForce;
|
||||
|
||||
#if CLIENT
|
||||
private Sound sound;
|
||||
|
||||
private ParticleEmitterPrefab particleEmitterPrefab;
|
||||
#endif
|
||||
|
||||
public readonly float Stun;
|
||||
|
||||
@@ -95,11 +98,13 @@ namespace Barotrauma
|
||||
|
||||
Stun = ToolBox.GetAttributeFloat(element, "stun", 0.0f);
|
||||
|
||||
#if CLIENT
|
||||
string soundPath = ToolBox.GetAttributeString(element, "sound", "");
|
||||
if (!string.IsNullOrWhiteSpace(soundPath))
|
||||
{
|
||||
sound = Sound.Load(soundPath);
|
||||
}
|
||||
#endif
|
||||
|
||||
Range = ToolBox.GetAttributeFloat(element, "range", 0.0f);
|
||||
|
||||
@@ -113,9 +118,11 @@ namespace Barotrauma
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
#if CLIENT
|
||||
case "particleemitter":
|
||||
particleEmitterPrefab = new ParticleEmitterPrefab(subElement);
|
||||
break;
|
||||
#endif
|
||||
case "statuseffect":
|
||||
statusEffects.Add(StatusEffect.Load(subElement));
|
||||
break;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
using FarseerPhysics;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Dynamics.Joints;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Particles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -17,26 +15,6 @@ namespace Barotrauma
|
||||
public static List<Character> CharacterList = new List<Character>();
|
||||
|
||||
public static bool DisableControls;
|
||||
|
||||
|
||||
//the Character that the player is currently controlling
|
||||
private static Character controlled;
|
||||
|
||||
public static Character Controlled
|
||||
{
|
||||
get { return controlled; }
|
||||
set
|
||||
{
|
||||
if (controlled == value) return;
|
||||
controlled = value;
|
||||
CharacterHUD.Reset();
|
||||
|
||||
if (controlled != null)
|
||||
{
|
||||
controlled.Enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool enabled = true;
|
||||
public bool Enabled
|
||||
@@ -97,8 +75,6 @@ namespace Barotrauma
|
||||
protected Item closestItem;
|
||||
private Character closestCharacter, selectedCharacter;
|
||||
|
||||
private Dictionary<object, HUDProgressBar> hudProgressBars;
|
||||
|
||||
private bool isDead;
|
||||
private CauseOfDeath lastAttackCauseOfDeath;
|
||||
private CauseOfDeath causeOfDeath;
|
||||
@@ -113,8 +89,6 @@ namespace Barotrauma
|
||||
|
||||
private float bleeding;
|
||||
|
||||
private List<CharacterSound> sounds;
|
||||
|
||||
private float attackCoolDown;
|
||||
|
||||
public Entity ViewTarget
|
||||
@@ -337,12 +311,7 @@ namespace Barotrauma
|
||||
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<object, HUDProgressBar> HUDProgressBars
|
||||
{
|
||||
get { return hudProgressBars; }
|
||||
}
|
||||
|
||||
|
||||
public HuskInfection huskInfection;
|
||||
public float HuskInfectionState
|
||||
{
|
||||
@@ -540,18 +509,11 @@ namespace Barotrauma
|
||||
: base(null)
|
||||
{
|
||||
keys = new Key[Enum.GetNames(typeof(InputType)).Length];
|
||||
|
||||
for (int i = 0; i < Enum.GetNames(typeof(InputType)).Length; i++)
|
||||
{
|
||||
keys[i] = new Key(GameMain.Config.KeyBind((InputType)i));
|
||||
}
|
||||
|
||||
|
||||
ConfigPath = file;
|
||||
|
||||
selectedItems = new Item[2];
|
||||
|
||||
hudProgressBars = new Dictionary<object, HUDProgressBar>();
|
||||
|
||||
IsRemotePlayer = isRemotePlayer;
|
||||
|
||||
oxygen = 100.0f;
|
||||
@@ -570,7 +532,9 @@ namespace Barotrauma
|
||||
|
||||
XDocument doc = ToolBox.TryLoadXml(file);
|
||||
if (doc == null || doc.Root == null) return;
|
||||
|
||||
|
||||
InitProjSpecific(doc);
|
||||
|
||||
SpeciesName = ToolBox.GetAttributeString(doc.Root, "name", "Unknown");
|
||||
|
||||
IsHumanoid = ToolBox.GetAttributeBool(doc.Root, "humanoid", false);
|
||||
@@ -599,16 +563,7 @@ namespace Barotrauma
|
||||
drowningTime = ToolBox.GetAttributeFloat(doc.Root, "drowningtime", 10.0f);
|
||||
|
||||
soundInterval = ToolBox.GetAttributeFloat(doc.Root, "soundinterval", 10.0f);
|
||||
|
||||
var soundElements = doc.Root.Elements("sound").ToList();
|
||||
|
||||
sounds = new List<CharacterSound>();
|
||||
foreach (XElement soundElement in soundElements)
|
||||
{
|
||||
sounds.Add(new CharacterSound(soundElement));
|
||||
}
|
||||
|
||||
|
||||
if (file == humanConfigFile)
|
||||
{
|
||||
if (Info.PickedItemIDs.Any())
|
||||
@@ -1275,14 +1230,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddAllToGUIUpdateList()
|
||||
{
|
||||
for (int i = 0; i < CharacterList.Count; i++)
|
||||
{
|
||||
CharacterList[i].AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateAll(Camera cam, float deltaTime)
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
@@ -1315,14 +1262,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void AddToGUIUpdateList()
|
||||
{
|
||||
if (controlled == this)
|
||||
{
|
||||
CharacterHUD.AddToGUIUpdateList(this);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Update(Camera cam, float deltaTime)
|
||||
{
|
||||
if (GameMain.Client != null && this == Controlled && !isSynced) return;
|
||||
@@ -1388,21 +1327,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (controlled == this)
|
||||
{
|
||||
Lights.LightManager.ViewTarget = this;
|
||||
CharacterHUD.Update(deltaTime, this);
|
||||
|
||||
foreach (HUDProgressBar progressBar in hudProgressBars.Values)
|
||||
{
|
||||
progressBar.Update(deltaTime);
|
||||
}
|
||||
|
||||
foreach (var pb in hudProgressBars.Where(pb => pb.Value.FadeTimer<=0.0f).ToList())
|
||||
{
|
||||
hudProgressBars.Remove(pb.Key);
|
||||
}
|
||||
}
|
||||
UpdateControlled(deltaTime);
|
||||
|
||||
if (Stun > 0.0f)
|
||||
{
|
||||
@@ -1522,10 +1447,12 @@ namespace Barotrauma
|
||||
float prevOxygen = oxygen;
|
||||
Oxygen += deltaTime * (oxygenAvailable < 30.0f ? -5.0f : 10.0f);
|
||||
|
||||
#if CLIENT
|
||||
if (prevOxygen > 0.0f && Oxygen <= 0.0f && controlled == this)
|
||||
{
|
||||
SoundPlayer.PlaySound("drown");
|
||||
}
|
||||
#endif
|
||||
|
||||
PressureProtection -= deltaTime * 100.0f;
|
||||
|
||||
@@ -1569,152 +1496,15 @@ namespace Barotrauma
|
||||
speechBubbleColor = color;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
|
||||
AnimController.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
public void DrawHUD(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
CharacterHUD.Draw(spriteBatch, this, cam);
|
||||
}
|
||||
|
||||
public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
AnimController.DebugDraw(spriteBatch);
|
||||
|
||||
if (aiTarget != null) aiTarget.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
/*if (memPos != null && memPos.Count > 0 && controlled == this)
|
||||
{
|
||||
PosInfo serverPos = memPos.Last();
|
||||
Vector2 remoteVec = ConvertUnits.ToDisplayUnits(serverPos.Position);
|
||||
if (Submarine != null)
|
||||
{
|
||||
remoteVec += Submarine.DrawPosition;
|
||||
}
|
||||
remoteVec.Y = -remoteVec.Y;
|
||||
|
||||
PosInfo localPos = memLocalPos.Find(m => m.ID == serverPos.ID);
|
||||
int mpind = memLocalPos.FindIndex(lp => lp.ID == localPos.ID);
|
||||
PosInfo localPos1 = mpind > 0 ? memLocalPos[mpind - 1] : null;
|
||||
PosInfo localPos2 = mpind < memLocalPos.Count-1 ? memLocalPos[mpind + 1] : null;
|
||||
|
||||
Vector2 localVec = ConvertUnits.ToDisplayUnits(localPos.Position);
|
||||
Vector2 localVec1 = localPos1 != null ? ConvertUnits.ToDisplayUnits(((PosInfo)localPos1).Position) : Vector2.Zero;
|
||||
Vector2 localVec2 = localPos2 != null ? ConvertUnits.ToDisplayUnits(((PosInfo)localPos2).Position) : Vector2.Zero;
|
||||
if (Submarine != null)
|
||||
{
|
||||
localVec += Submarine.DrawPosition;
|
||||
localVec1 += Submarine.DrawPosition;
|
||||
localVec2 += Submarine.DrawPosition;
|
||||
}
|
||||
localVec.Y = -localVec.Y;
|
||||
localVec1.Y = -localVec1.Y;
|
||||
localVec2.Y = -localVec2.Y;
|
||||
|
||||
//GUI.DrawLine(spriteBatch, remoteVec, localVec, Color.Yellow, 0, 10);
|
||||
if (localPos1 != null) GUI.DrawLine(spriteBatch, remoteVec, localVec1, Color.Lime, 0, 2);
|
||||
if (localPos2 != null) GUI.DrawLine(spriteBatch, remoteVec + Vector2.One, localVec2 + Vector2.One, Color.Red, 0, 2);
|
||||
}
|
||||
|
||||
Vector2 mouseDrawPos = CursorWorldPosition;
|
||||
mouseDrawPos.Y = -mouseDrawPos.Y;
|
||||
GUI.DrawLine(spriteBatch, mouseDrawPos - new Vector2(0, 5), mouseDrawPos + new Vector2(0, 5), Color.Red, 0, 10);
|
||||
|
||||
Vector2 closestItemPos = closestItem != null ? closestItem.DrawPosition : Vector2.Zero;
|
||||
closestItemPos.Y = -closestItemPos.Y;
|
||||
GUI.DrawLine(spriteBatch, closestItemPos - new Vector2(0, 5), closestItemPos + new Vector2(0, 5), Color.Lime, 0, 10);*/
|
||||
|
||||
if (this == controlled || GUI.DisableHUD) return;
|
||||
|
||||
Vector2 pos = DrawPosition;
|
||||
pos.Y = -pos.Y;
|
||||
|
||||
if (speechBubbleTimer > 0.0f)
|
||||
{
|
||||
GUI.SpeechBubbleIcon.Draw(spriteBatch, pos - Vector2.UnitY * 100.0f,
|
||||
speechBubbleColor * Math.Min(speechBubbleTimer, 1.0f), 0.0f,
|
||||
Math.Min((float)speechBubbleTimer, 1.0f));
|
||||
}
|
||||
|
||||
if (this == controlled) return;
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
Vector2 namePos = new Vector2(pos.X, pos.Y - 110.0f - (5.0f / cam.Zoom)) - GUI.Font.MeasureString(Info.Name) * 0.5f / cam.Zoom;
|
||||
Color nameColor = Color.White;
|
||||
|
||||
if (Character.Controlled != null && TeamID != Character.Controlled.TeamID)
|
||||
{
|
||||
nameColor = Color.Red;
|
||||
}
|
||||
GUI.Font.DrawString(spriteBatch, Info.Name, namePos + new Vector2(1.0f / cam.Zoom, 1.0f / cam.Zoom), Color.Black, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.001f);
|
||||
GUI.Font.DrawString(spriteBatch, Info.Name, namePos, nameColor, 0.0f, Vector2.Zero, 1.0f / cam.Zoom, SpriteEffects.None, 0.0f);
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
GUI.Font.DrawString(spriteBatch, ID.ToString(), namePos - new Vector2(0.0f, 20.0f), Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDead) return;
|
||||
|
||||
if (health < maxHealth * 0.98f)
|
||||
{
|
||||
Vector2 healthBarPos = new Vector2(pos.X - 50, DrawPosition.Y + 100.0f);
|
||||
|
||||
GUI.DrawProgressBar(spriteBatch, healthBarPos, new Vector2(100.0f, 15.0f), health / maxHealth, Color.Lerp(Color.Red, Color.Green, health / maxHealth) * 0.8f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a progress bar that's "linked" to the specified object (or updates an existing one if there's one already linked to the object)
|
||||
/// The progress bar will automatically fade out after 1 sec if the method hasn't been called during that time
|
||||
/// </summary>
|
||||
public HUDProgressBar UpdateHUDProgressBar(object linkedObject, Vector2 worldPosition, float progress, Color emptyColor, Color fullColor)
|
||||
{
|
||||
if (controlled != this) return null;
|
||||
|
||||
HUDProgressBar progressBar = null;
|
||||
if (!hudProgressBars.TryGetValue(linkedObject, out progressBar))
|
||||
{
|
||||
progressBar = new HUDProgressBar(worldPosition, Submarine, emptyColor, fullColor);
|
||||
hudProgressBars.Add(linkedObject, progressBar);
|
||||
}
|
||||
|
||||
progressBar.WorldPosition = worldPosition;
|
||||
progressBar.FadeTimer = Math.Max(progressBar.FadeTimer, 1.0f);
|
||||
progressBar.Progress = progress;
|
||||
|
||||
return progressBar;
|
||||
}
|
||||
|
||||
public void PlaySound(CharacterSound.SoundType soundType)
|
||||
{
|
||||
if (sounds == null || sounds.Count == 0) return;
|
||||
|
||||
var matchingSounds = sounds.FindAll(s => s.Type == soundType);
|
||||
if (matchingSounds.Count == 0) return;
|
||||
|
||||
var selectedSound = matchingSounds[Rand.Int(matchingSounds.Count)];
|
||||
selectedSound.Sound.Play(1.0f, selectedSound.Range, AnimController.WorldPosition);
|
||||
}
|
||||
|
||||
public virtual void AddDamage(CauseOfDeath causeOfDeath, float amount, IDamageable attacker)
|
||||
{
|
||||
Health = health-amount;
|
||||
if (amount > 0.0f)
|
||||
{
|
||||
lastAttackCauseOfDeath = causeOfDeath;
|
||||
#if CLIENT
|
||||
if (controlled == this) CharacterHUD.TakeDamage(amount);
|
||||
#endif
|
||||
}
|
||||
if (health <= minHealth) Kill(causeOfDeath);
|
||||
}
|
||||
@@ -1820,19 +1610,7 @@ namespace Barotrauma
|
||||
// limb.Damage = 100.0f;
|
||||
}
|
||||
|
||||
SoundPlayer.PlaySound("implode", 1.0f, 150.0f, WorldPosition);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Particle p = GameMain.ParticleManager.CreateParticle("waterblood",
|
||||
ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f),
|
||||
Rand.Vector(10.0f));
|
||||
if (p != null) p.Size *= 2.0f;
|
||||
|
||||
GameMain.ParticleManager.CreateParticle("bubbles",
|
||||
ConvertUnits.ToDisplayUnits(centerOfMass) + Rand.Vector(5.0f),
|
||||
new Vector2(Rand.Range(-50f, 50f), Rand.Range(-100f, 50f)));
|
||||
}
|
||||
ImplodeFX();
|
||||
|
||||
foreach (var joint in AnimController.limbJoints)
|
||||
{
|
||||
@@ -1852,6 +1630,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.NetworkMember != null)
|
||||
{
|
||||
#if CLIENT
|
||||
if (Character.controlled == this)
|
||||
{
|
||||
string chatMessage = InfoTextManager.GetInfoText("Self_CauseOfDeath." + causeOfDeath.ToString());
|
||||
@@ -1861,6 +1640,7 @@ namespace Barotrauma
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
controlled = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GameMain.Server != null)
|
||||
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.Status });
|
||||
@@ -1871,8 +1651,10 @@ namespace Barotrauma
|
||||
GameServer.Log(Name+" has died (Cause of death: "+causeOfDeath+")", ServerLog.MessageType.Attack);
|
||||
|
||||
if (OnDeath != null) OnDeath(this, causeOfDeath);
|
||||
|
||||
|
||||
#if CLIENT
|
||||
PlaySound(CharacterSound.SoundType.Die);
|
||||
#endif
|
||||
|
||||
isDead = true;
|
||||
|
||||
@@ -1935,7 +1717,15 @@ namespace Barotrauma
|
||||
|
||||
CharacterList.Remove(this);
|
||||
|
||||
#if CLIENT
|
||||
if (controlled == this) controlled = null;
|
||||
|
||||
if (GameMain.GameSession?.CrewManager != null &&
|
||||
GameMain.GameSession.CrewManager.characters.Contains(this))
|
||||
{
|
||||
GameMain.GameSession.CrewManager.characters.Remove(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GameMain.Client != null && GameMain.Client.Character == this) GameMain.Client.Character = null;
|
||||
|
||||
@@ -1948,12 +1738,6 @@ namespace Barotrauma
|
||||
if (selectedItems[0] != null) selectedItems[0].Drop(this);
|
||||
if (selectedItems[1] != null) selectedItems[1].Drop(this);
|
||||
|
||||
if (GameMain.GameSession?.CrewManager != null &&
|
||||
GameMain.GameSession.CrewManager.characters.Contains(this))
|
||||
{
|
||||
GameMain.GameSession.CrewManager.characters.Remove(this);
|
||||
}
|
||||
|
||||
foreach (Character c in CharacterList)
|
||||
{
|
||||
if (c.closestCharacter == this) c.closestCharacter = null;
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CharacterHUD
|
||||
{
|
||||
private static Sprite statusIcons;
|
||||
|
||||
private static Sprite noiseOverlay, damageOverlay;
|
||||
|
||||
private static GUIButton cprButton;
|
||||
|
||||
private static GUIButton suicideButton;
|
||||
|
||||
private static GUIProgressBar drowningBar, healthBar;
|
||||
|
||||
public static float damageOverlayTimer { get; private set; }
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
damageOverlayTimer = 0.0f;
|
||||
}
|
||||
|
||||
public static void TakeDamage(float amount)
|
||||
{
|
||||
healthBar.Flash();
|
||||
|
||||
damageOverlayTimer = MathHelper.Clamp(amount * 0.1f, 0.2f, 5.0f);
|
||||
}
|
||||
|
||||
public static void AddToGUIUpdateList(Character character)
|
||||
{
|
||||
if (GUI.DisableHUD) return;
|
||||
|
||||
if (cprButton != null && cprButton.Visible) cprButton.AddToGUIUpdateList();
|
||||
|
||||
if (suicideButton != null && suicideButton.Visible) suicideButton.AddToGUIUpdateList();
|
||||
|
||||
if (!character.IsUnconscious && character.Stun <= 0.0f)
|
||||
{
|
||||
|
||||
if (character.Inventory != null)
|
||||
{
|
||||
for (int i = 0; i < character.Inventory.Items.Length - 1; i++)
|
||||
{
|
||||
var item = character.Inventory.Items[i];
|
||||
if (item == null || CharacterInventory.limbSlots[i] == InvSlotType.Any) continue;
|
||||
|
||||
foreach (ItemComponent ic in item.components)
|
||||
{
|
||||
if (ic.DrawHudWhenEquipped) ic.AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Update(float deltaTime, Character character)
|
||||
{
|
||||
if (drowningBar != null)
|
||||
{
|
||||
drowningBar.Update(deltaTime);
|
||||
if (character.Oxygen < 10.0f) drowningBar.Flash();
|
||||
}
|
||||
if (healthBar != null) healthBar.Update(deltaTime);
|
||||
|
||||
if (cprButton != null && cprButton.Visible) cprButton.Update(deltaTime);
|
||||
|
||||
if (suicideButton != null && suicideButton.Visible) suicideButton.Update(deltaTime);
|
||||
|
||||
if (damageOverlayTimer > 0.0f) damageOverlayTimer -= deltaTime;
|
||||
|
||||
if (!character.IsUnconscious && character.Stun <= 0.0f)
|
||||
{
|
||||
|
||||
if (character.Inventory != null)
|
||||
{
|
||||
if (!character.LockHands && character.Stun >= -0.1f)
|
||||
{
|
||||
character.Inventory.Update(deltaTime);
|
||||
}
|
||||
|
||||
for (int i = 0; i < character.Inventory.Items.Length - 1; i++)
|
||||
{
|
||||
var item = character.Inventory.Items[i];
|
||||
if (item == null || CharacterInventory.limbSlots[i] == InvSlotType.Any) continue;
|
||||
|
||||
foreach (ItemComponent ic in item.components)
|
||||
{
|
||||
if (ic.DrawHudWhenEquipped) ic.UpdateHUD(character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
|
||||
{
|
||||
character.SelectedCharacter.Inventory.Update(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Draw(SpriteBatch spriteBatch, Character character, Camera cam)
|
||||
{
|
||||
if (statusIcons == null)
|
||||
{
|
||||
statusIcons = new Sprite("Content/UI/statusIcons.png", Vector2.Zero);
|
||||
}
|
||||
|
||||
if (noiseOverlay == null)
|
||||
{
|
||||
noiseOverlay = new Sprite("Content/UI/noise.png", Vector2.Zero);
|
||||
}
|
||||
|
||||
if (damageOverlay == null)
|
||||
{
|
||||
damageOverlay = new Sprite("Content/UI/damageOverlay.png", Vector2.Zero);
|
||||
}
|
||||
|
||||
if (GUI.DisableHUD) return;
|
||||
|
||||
if (character.Inventory != null)
|
||||
{
|
||||
for (int i = 0; i < character.Inventory.Items.Length - 1; i++)
|
||||
{
|
||||
var item = character.Inventory.Items[i];
|
||||
if (item == null || CharacterInventory.limbSlots[i] == InvSlotType.Any) continue;
|
||||
|
||||
foreach (ItemComponent ic in item.components)
|
||||
{
|
||||
if (ic.DrawHudWhenEquipped) ic.DrawHUD(spriteBatch, character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrawStatusIcons(spriteBatch, character);
|
||||
|
||||
if (!character.IsUnconscious && character.Stun <= 0.0f)
|
||||
{
|
||||
if (character.Inventory != null && !character.LockHands && character.Stun >= -0.1f)
|
||||
{
|
||||
character.Inventory.DrawOffset = Vector2.Zero;
|
||||
character.Inventory.DrawOwn(spriteBatch);
|
||||
}
|
||||
|
||||
if (character.SelectedCharacter != null && character.SelectedCharacter.Inventory != null)
|
||||
{
|
||||
character.SelectedCharacter.Inventory.DrawOffset = new Vector2(320.0f, 0.0f);
|
||||
character.SelectedCharacter.Inventory.DrawOwn(spriteBatch);
|
||||
|
||||
if (cprButton == null)
|
||||
{
|
||||
cprButton = new GUIButton(
|
||||
new Rectangle(character.SelectedCharacter.Inventory.SlotPositions[0].ToPoint() + new Point(320, -30), new Point(130, 20)), "Perform CPR", "");
|
||||
|
||||
cprButton.OnClicked = (button, userData) =>
|
||||
{
|
||||
if (Character.Controlled == null || Character.Controlled.SelectedCharacter == null) return false;
|
||||
|
||||
Character.Controlled.AnimController.Anim = (Character.Controlled.AnimController.Anim == AnimController.Animation.CPR) ?
|
||||
AnimController.Animation.None : AnimController.Animation.CPR;
|
||||
|
||||
foreach (Limb limb in Character.Controlled.SelectedCharacter.AnimController.Limbs)
|
||||
{
|
||||
limb.pullJoint.Enabled = false;
|
||||
}
|
||||
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Repair });
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
//cprButton.Visible = character.GetSkillLevel("Medical") > 20.0f;
|
||||
|
||||
if (cprButton.Visible) cprButton.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
if (character.ClosestCharacter != null && character.ClosestCharacter.CanBeSelected)
|
||||
{
|
||||
Vector2 startPos = character.DrawPosition + (character.ClosestCharacter.DrawPosition - character.DrawPosition) * 0.7f;
|
||||
startPos = cam.WorldToScreen(startPos);
|
||||
|
||||
Vector2 textPos = startPos;
|
||||
textPos -= new Vector2(GUI.Font.MeasureString(character.ClosestCharacter.Info.Name).X / 2, 20);
|
||||
|
||||
GUI.DrawString(spriteBatch, textPos, character.ClosestCharacter.Info.Name, Color.White, Color.Black, 2);
|
||||
}
|
||||
else if (character.SelectedCharacter == null && character.ClosestItem != null && character.SelectedConstruction == null)
|
||||
{
|
||||
var hudTexts = character.ClosestItem.GetHUDTexts(character);
|
||||
|
||||
Vector2 startPos = new Vector2((int)(GameMain.GraphicsWidth / 2.0f), GameMain.GraphicsHeight);
|
||||
startPos.Y -= 50 + hudTexts.Count * 25;
|
||||
|
||||
Vector2 textPos = startPos;
|
||||
textPos -= new Vector2((int)GUI.Font.MeasureString(character.ClosestItem.Name).X / 2, 20);
|
||||
|
||||
GUI.DrawString(spriteBatch, textPos, character.ClosestItem.Name, Color.White, Color.Black * 0.7f, 2);
|
||||
|
||||
textPos.Y += 30.0f;
|
||||
foreach (ColoredText coloredText in hudTexts)
|
||||
{
|
||||
textPos.X = (int)(startPos.X - GUI.SmallFont.MeasureString(coloredText.Text).X / 2);
|
||||
|
||||
GUI.DrawString(spriteBatch, textPos, coloredText.Text, coloredText.Color, Color.Black * 0.7f, 2, GUI.SmallFont);
|
||||
|
||||
textPos.Y += 25;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (HUDProgressBar progressBar in character.HUDProgressBars.Values)
|
||||
{
|
||||
progressBar.Draw(spriteBatch, cam);
|
||||
}
|
||||
}
|
||||
|
||||
if (Screen.Selected == GameMain.EditMapScreen) return;
|
||||
|
||||
if (character.IsUnconscious || (character.Oxygen < 80.0f && !character.IsDead))
|
||||
{
|
||||
Vector2 offset = Rand.Vector(noiseOverlay.size.X);
|
||||
offset.X = Math.Abs(offset.X);
|
||||
offset.Y = Math.Abs(offset.Y);
|
||||
|
||||
float alpha = character.IsUnconscious ? 1.0f : Math.Min((80.0f - character.Oxygen)/50.0f, 0.8f);
|
||||
|
||||
noiseOverlay.DrawTiled(spriteBatch, Vector2.Zero - offset, new Vector2(GameMain.GraphicsWidth, GameMain.GraphicsHeight) + offset,
|
||||
Vector2.Zero,
|
||||
Color.White * alpha);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (suicideButton != null) suicideButton.Visible = false;
|
||||
}
|
||||
|
||||
if (damageOverlayTimer>0.0f)
|
||||
{
|
||||
damageOverlay.Draw(spriteBatch, Vector2.Zero, Color.White * damageOverlayTimer, Vector2.Zero, 0.0f,
|
||||
new Vector2(GameMain.GraphicsWidth / damageOverlay.size.X, GameMain.GraphicsHeight / damageOverlay.size.Y));
|
||||
}
|
||||
|
||||
if (character.IsUnconscious && !character.IsDead)
|
||||
{
|
||||
if (suicideButton == null)
|
||||
{
|
||||
suicideButton = new GUIButton(
|
||||
new Rectangle(new Point(GameMain.GraphicsWidth / 2 - 60, 20), new Point(120, 20)), "Give in", "");
|
||||
|
||||
|
||||
suicideButton.ToolTip = GameMain.NetworkMember == null ?
|
||||
"The character can no longer be revived if you give in." :
|
||||
"Let go of your character and enter spectator mode (other players will no longer be able to revive you)";
|
||||
|
||||
suicideButton.OnClicked = (button, userData) =>
|
||||
{
|
||||
GUIComponent.ForceMouseOn(null);
|
||||
if (Character.Controlled != null)
|
||||
{
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Status });
|
||||
}
|
||||
else
|
||||
{
|
||||
Character.Controlled.Kill(Character.Controlled.CauseOfDeath);
|
||||
Character.Controlled = null;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
suicideButton.Visible = true;
|
||||
suicideButton.Draw(spriteBatch);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawStatusIcons(SpriteBatch spriteBatch, Character character)
|
||||
{
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
GUI.DrawString(spriteBatch, new Vector2(30, GameMain.GraphicsHeight - 260), "Stun: "+character.Stun, Color.White);
|
||||
}
|
||||
|
||||
if (drowningBar == null)
|
||||
{
|
||||
int width = 100, height = 20;
|
||||
|
||||
drowningBar = new GUIProgressBar(new Rectangle(30, GameMain.GraphicsHeight - 200, width, height), Color.Blue, "", 1.0f, Alignment.TopLeft);
|
||||
new GUIImage(new Rectangle(-27, -7, 20, 20), new Rectangle(17, 0, 20, 24), statusIcons, Alignment.TopLeft, drowningBar);
|
||||
|
||||
healthBar = new GUIProgressBar(new Rectangle(30, GameMain.GraphicsHeight - 230, width, height), Color.Red, "", 1.0f, Alignment.TopLeft);
|
||||
new GUIImage(new Rectangle(-26, -7, 20, 20), new Rectangle(0, 0, 13, 24), statusIcons, Alignment.TopLeft, healthBar);
|
||||
}
|
||||
|
||||
drowningBar.BarSize = character.Oxygen / 100.0f;
|
||||
if (drowningBar.BarSize < 0.99f)
|
||||
{
|
||||
drowningBar.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
healthBar.BarSize = character.Health / character.MaxHealth;
|
||||
if (healthBar.BarSize < 1.0f)
|
||||
{
|
||||
healthBar.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
float bloodDropCount = character.Bleeding;
|
||||
bloodDropCount = MathHelper.Clamp(bloodDropCount, 0.0f, 5.0f);
|
||||
for (int i = 0; i < Math.Ceiling(bloodDropCount); i++)
|
||||
{
|
||||
float alpha = MathHelper.Clamp(bloodDropCount-i, 0.2f, 1.0f);
|
||||
spriteBatch.Draw(statusIcons.Texture, new Vector2(25.0f + 20 * i, healthBar.Rect.Y - 20.0f), new Rectangle(39, 3, 15, 19), Color.White * alpha);
|
||||
}
|
||||
|
||||
float pressureFactor = (character.AnimController.CurrentHull == null) ?
|
||||
100.0f : Math.Min(character.AnimController.CurrentHull.LethalPressure,100.0f);
|
||||
if (character.PressureProtection > 0.0f) pressureFactor = 0.0f;
|
||||
|
||||
if (pressureFactor>0.0f)
|
||||
{
|
||||
float indicatorAlpha = ((float)Math.Sin(character.PressureTimer * 0.1f) + 1.0f) * 0.5f;
|
||||
|
||||
indicatorAlpha = MathHelper.Clamp(indicatorAlpha, 0.1f, pressureFactor/100.0f);
|
||||
|
||||
spriteBatch.Draw(statusIcons.Texture, new Vector2(10.0f, healthBar.Rect.Y - 60.0f), new Rectangle(0, 24, 24, 25), Color.White * indicatorAlpha);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -10,7 +9,7 @@ namespace Barotrauma
|
||||
{
|
||||
public enum Gender { None, Male, Female };
|
||||
|
||||
class CharacterInfo
|
||||
partial class CharacterInfo
|
||||
{
|
||||
public string Name;
|
||||
|
||||
@@ -211,66 +210,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public GUIFrame CreateInfoFrame(Rectangle rect)
|
||||
{
|
||||
GUIFrame frame = new GUIFrame(rect, Color.Transparent);
|
||||
frame.Padding = new Vector4(10.0f,10.0f,10.0f,10.0f);
|
||||
|
||||
return CreateInfoFrame(frame);
|
||||
}
|
||||
|
||||
public GUIFrame CreateInfoFrame(GUIFrame frame)
|
||||
{
|
||||
new GUIImage(new Rectangle(0,0,30,30), HeadSprite, Alignment.TopLeft, frame);
|
||||
|
||||
ScalableFont font = frame.Rect.Width<280 ? GUI.SmallFont : GUI.Font;
|
||||
|
||||
int x = 0, y = 0;
|
||||
new GUITextBlock(new Rectangle(x+60, y, 200, 20), Name, "", frame, font);
|
||||
y += 20;
|
||||
|
||||
if (Job!=null)
|
||||
{
|
||||
new GUITextBlock(new Rectangle(x + 60, y, 200, 20), Job.Name, "", frame, font);
|
||||
y += 30;
|
||||
|
||||
var skills = Job.Skills;
|
||||
skills.Sort((s1, s2) => -s1.Level.CompareTo(s2.Level));
|
||||
|
||||
new GUITextBlock(new Rectangle(x, y, 200, 20), "Skills:", "", frame, font);
|
||||
y += 20;
|
||||
foreach (Skill skill in skills)
|
||||
{
|
||||
Color textColor = Color.White * (0.5f + skill.Level/200.0f);
|
||||
new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Name, Color.Transparent, textColor, Alignment.Left, "", frame).Font = font;
|
||||
new GUITextBlock(new Rectangle(x, y, 200, 20), skill.Level.ToString(), Color.Transparent, textColor, Alignment.Right, "", frame).Font = font;
|
||||
y += 20;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
public GUIFrame CreateCharacterFrame(GUIComponent parent, string text, object userData)
|
||||
{
|
||||
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 40), Color.Transparent, "ListBoxElement", parent);
|
||||
frame.UserData = userData;
|
||||
|
||||
GUITextBlock textBlock = new GUITextBlock(
|
||||
new Rectangle(40, 0, 0, 25),
|
||||
text,
|
||||
null, null,
|
||||
Alignment.Left, Alignment.Left,
|
||||
"", frame, false);
|
||||
textBlock.Font = GUI.SmallFont;
|
||||
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
|
||||
|
||||
new GUIImage(new Rectangle(-5, -5, 0, 0), HeadSprite, Alignment.Left, frame);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
public void UpdateCharacterItems()
|
||||
{
|
||||
pickedItems.Clear();
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CharacterSound
|
||||
{
|
||||
public enum SoundType
|
||||
{
|
||||
Idle, Attack, Die
|
||||
}
|
||||
|
||||
public readonly Sound Sound;
|
||||
|
||||
public readonly SoundType Type;
|
||||
|
||||
public readonly float Range;
|
||||
|
||||
public CharacterSound(XElement element)
|
||||
{
|
||||
Sound = Sound.Load(element.Attribute("file").Value);
|
||||
Range = ToolBox.GetAttributeFloat(element, "range", 1000.0f);
|
||||
|
||||
Enum.TryParse<SoundType>(ToolBox.GetAttributeString(element, "state", "Idle"), true, out Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class HUDProgressBar
|
||||
{
|
||||
private float progress;
|
||||
|
||||
public float Progress
|
||||
{
|
||||
get { return progress; }
|
||||
set { progress = MathHelper.Clamp(value, 0.0f, 1.0f); }
|
||||
}
|
||||
|
||||
public float FadeTimer;
|
||||
|
||||
private Color fullColor, emptyColor;
|
||||
|
||||
private Vector2 worldPosition;
|
||||
|
||||
public Vector2 WorldPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return worldPosition;
|
||||
}
|
||||
set
|
||||
{
|
||||
worldPosition = value;
|
||||
if (parentSub != null)
|
||||
{
|
||||
worldPosition -= parentSub.DrawPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 Size;
|
||||
|
||||
private Submarine parentSub;
|
||||
|
||||
public HUDProgressBar(Vector2 worldPosition, Submarine parentSubmarine = null)
|
||||
: this(worldPosition, parentSubmarine, Color.Red, Color.Green)
|
||||
{
|
||||
}
|
||||
|
||||
public HUDProgressBar(Vector2 worldPosition, Submarine parentSubmarine, Color emptyColor, Color fullColor)
|
||||
{
|
||||
this.emptyColor = emptyColor;
|
||||
this.fullColor = fullColor;
|
||||
|
||||
parentSub = parentSubmarine;
|
||||
|
||||
WorldPosition = worldPosition;
|
||||
|
||||
Size = new Vector2(100.0f, 20.0f);
|
||||
|
||||
FadeTimer = 1.0f;
|
||||
}
|
||||
|
||||
public void Update(float deltatime)
|
||||
{
|
||||
FadeTimer -= deltatime;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
float a = Math.Min(FadeTimer, 1.0f);
|
||||
|
||||
Vector2 pos = new Vector2(WorldPosition.X - Size.X / 2, WorldPosition.Y + Size.Y / 2);
|
||||
|
||||
if (parentSub != null)
|
||||
{
|
||||
pos += parentSub.DrawPosition;
|
||||
}
|
||||
|
||||
pos = cam.WorldToScreen(pos);
|
||||
|
||||
GUI.DrawProgressBar(spriteBatch,
|
||||
new Vector2(pos.X, -pos.Y),
|
||||
Size, progress,
|
||||
Color.Lerp(emptyColor, fullColor, progress) * a,
|
||||
Color.White * a * 0.8f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class JobPrefab
|
||||
partial class JobPrefab
|
||||
{
|
||||
public static List<JobPrefab> List;
|
||||
|
||||
@@ -102,52 +102,6 @@ namespace Barotrauma
|
||||
return List[Rand.Int(List.Count)];
|
||||
}
|
||||
|
||||
public GUIFrame CreateInfoFrame()
|
||||
{
|
||||
int width = 500, height = 400;
|
||||
|
||||
GUIFrame backFrame = new GUIFrame(Rectangle.Empty, Color.Black*0.5f);
|
||||
backFrame.Padding = Vector4.Zero;
|
||||
|
||||
GUIFrame frame = new GUIFrame(new Rectangle(GameMain.GraphicsWidth / 2 - width / 2, GameMain.GraphicsHeight / 2 - height / 2, width, height), "", backFrame);
|
||||
frame.Padding = new Vector4(30.0f, 30.0f, 30.0f, 30.0f);
|
||||
|
||||
new GUITextBlock(new Rectangle(0,0,100,20), Name, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont);
|
||||
|
||||
var descriptionBlock = new GUITextBlock(new Rectangle(0, 40, 0, 0), Description, "", Alignment.TopLeft, Alignment.TopLeft, frame, true, GUI.SmallFont);
|
||||
|
||||
new GUITextBlock(new Rectangle(0, 40 + descriptionBlock.Rect.Height + 20, 100, 20), "Skills: ", "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont);
|
||||
|
||||
int y = 40 + descriptionBlock.Rect.Height + 50;
|
||||
foreach (SkillPrefab skill in Skills)
|
||||
{
|
||||
string skillDescription = Skill.GetLevelName((int)skill.LevelRange.X);
|
||||
string skillDescription2 = Skill.GetLevelName((int)skill.LevelRange.Y);
|
||||
|
||||
if (skillDescription2!= skillDescription)
|
||||
{
|
||||
skillDescription += "/"+skillDescription2;
|
||||
}
|
||||
new GUITextBlock(new Rectangle(0, y, 100, 20),
|
||||
" - " + skill.Name + ": " + skillDescription, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont);
|
||||
|
||||
y += 20;
|
||||
}
|
||||
|
||||
new GUITextBlock(new Rectangle(250, 40 + descriptionBlock.Rect.Height + 20, 0, 20), "Items: ", "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.LargeFont);
|
||||
|
||||
y = 40 + descriptionBlock.Rect.Height + 50;
|
||||
foreach (string itemName in ItemNames)
|
||||
{
|
||||
new GUITextBlock(new Rectangle(250, y, 100, 20),
|
||||
" - " + itemName, "", Alignment.TopLeft, Alignment.TopLeft, frame, false, GUI.SmallFont);
|
||||
|
||||
y += 20;
|
||||
}
|
||||
|
||||
return backFrame;
|
||||
}
|
||||
|
||||
public static void LoadAll(List<string> filePaths)
|
||||
{
|
||||
List = new List<JobPrefab>();
|
||||
|
||||
@@ -4,7 +4,7 @@ using FarseerPhysics;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using FarseerPhysics.Dynamics.Joints;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
//using Microsoft.Xna.Framework.Graphics;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.Lights;
|
||||
@@ -19,7 +19,7 @@ namespace Barotrauma
|
||||
LeftLeg, RightLeg, LeftFoot, RightFoot, Head, Torso, Tail, Legs, RightThigh, LeftThigh, Waist
|
||||
};
|
||||
|
||||
class Limb
|
||||
partial class Limb
|
||||
{
|
||||
private const float LimbDensity = 15;
|
||||
private const float LimbAngularDamping = 7;
|
||||
@@ -54,7 +54,6 @@ namespace Barotrauma
|
||||
private readonly Vector2 armorSector;
|
||||
private readonly float armorValue;
|
||||
|
||||
Sound hitSound;
|
||||
//a timer for delaying when a hitsound/attacksound can be played again
|
||||
public float soundTimer;
|
||||
public const float SoundInterval = 0.4f;
|
||||
@@ -109,12 +108,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
public Sound HitSound
|
||||
{
|
||||
get { return hitSound; }
|
||||
}
|
||||
|
||||
|
||||
public Vector2 LinearVelocity
|
||||
{
|
||||
get { return body.LinearVelocity; }
|
||||
@@ -313,9 +307,11 @@ namespace Barotrauma
|
||||
case "attack":
|
||||
attack = new Attack(subElement);
|
||||
break;
|
||||
#if CLIENT
|
||||
case "sound":
|
||||
hitSound = Sound.Load(ToolBox.GetAttributeString(subElement, "file", ""));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -335,8 +331,6 @@ namespace Barotrauma
|
||||
|
||||
public AttackResult AddDamage(Vector2 position, DamageType damageType, float amount, float bleedingAmount, bool playSound)
|
||||
{
|
||||
DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash;
|
||||
|
||||
bool hitArmor = false;
|
||||
float totalArmorValue = 0.0f;
|
||||
|
||||
@@ -355,8 +349,15 @@ namespace Barotrauma
|
||||
totalArmorValue += wearable.WearableComponent.ArmorValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Bleeding += bleedingAmount;
|
||||
//Damage += amount;
|
||||
|
||||
#if CLIENT
|
||||
float bloodAmount = hitArmor || bleedingAmount <= 0.0f ? 0 : (int)Math.Min((int)(amount * 2.0f), 20);
|
||||
|
||||
DamageSoundType damageSoundType = (damageType == DamageType.Blunt) ? DamageSoundType.LimbBlunt : DamageSoundType.LimbSlash;
|
||||
|
||||
if (hitArmor)
|
||||
{
|
||||
totalArmorValue = Math.Max(totalArmorValue, 0.0f);
|
||||
@@ -371,11 +372,6 @@ namespace Barotrauma
|
||||
SoundPlayer.PlayDamageSound(damageSoundType, amount, position);
|
||||
}
|
||||
|
||||
//Bleeding += bleedingAmount;
|
||||
//Damage += amount;
|
||||
|
||||
float bloodAmount = hitArmor || bleedingAmount<=0.0f ? 0 : (int)Math.Min((int)(amount * 2.0f), 20);
|
||||
|
||||
for (int i = 0; i < bloodAmount; i++)
|
||||
{
|
||||
Vector2 particleVel = SimPosition - position;
|
||||
@@ -390,6 +386,7 @@ namespace Barotrauma
|
||||
{
|
||||
GameMain.ParticleManager.CreateParticle("waterblood", WorldPosition, Vector2.Zero, 0.0f, character.AnimController.CurrentHull);
|
||||
}
|
||||
#endif
|
||||
|
||||
damage += Math.Max(amount,bleedingAmount) / character.MaxHealth * 100.0f;
|
||||
|
||||
@@ -479,77 +476,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
float brightness = 1.0f - (burnt / 100.0f) * 0.5f;
|
||||
Color color = new Color(brightness, brightness, brightness);
|
||||
|
||||
body.Dir = Dir;
|
||||
|
||||
bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb);
|
||||
|
||||
if (!hideLimb)
|
||||
{
|
||||
body.Draw(spriteBatch, sprite, color, null, scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
body.UpdateDrawPosition();
|
||||
}
|
||||
|
||||
if (LightSource != null)
|
||||
{
|
||||
LightSource.Position = body.DrawPosition;
|
||||
}
|
||||
|
||||
foreach (WearableSprite wearable in wearingItems)
|
||||
{
|
||||
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
|
||||
|
||||
Vector2 origin = wearable.Sprite.Origin;
|
||||
if (body.Dir == -1.0f) origin.X = wearable.Sprite.SourceRect.Width - origin.X;
|
||||
|
||||
float depth = sprite.Depth - 0.000001f;
|
||||
|
||||
if (wearable.DepthLimb != LimbType.None)
|
||||
{
|
||||
Limb depthLimb = character.AnimController.GetLimb(wearable.DepthLimb);
|
||||
if (depthLimb != null)
|
||||
{
|
||||
depth = depthLimb.sprite.Depth - 0.000001f;
|
||||
}
|
||||
}
|
||||
|
||||
wearable.Sprite.Draw(spriteBatch,
|
||||
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
||||
color, origin,
|
||||
-body.DrawRotation,
|
||||
scale, spriteEffect, depth);
|
||||
}
|
||||
|
||||
if (damage > 0.0f && damagedSprite != null && !hideLimb)
|
||||
{
|
||||
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
|
||||
|
||||
float depth = sprite.Depth - 0.0000015f;
|
||||
|
||||
damagedSprite.Draw(spriteBatch,
|
||||
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
||||
color * Math.Min(damage / 50.0f, 1.0f), sprite.Origin,
|
||||
-body.DrawRotation,
|
||||
1.0f, spriteEffect, depth);
|
||||
}
|
||||
|
||||
if (!GameMain.DebugDraw) return;
|
||||
|
||||
if (pullJoint != null)
|
||||
{
|
||||
Vector2 pos = ConvertUnits.ToDisplayUnits(pullJoint.WorldAnchorB);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)pos.X, (int)-pos.Y, 5, 5), Color.Red, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
if (sprite != null)
|
||||
@@ -574,11 +500,13 @@ namespace Barotrauma
|
||||
body = null;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (hitSound != null)
|
||||
{
|
||||
hitSound.Remove();
|
||||
hitSound = null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
using Barotrauma.Particles;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
#if CLIENT
|
||||
using Barotrauma.Particles;
|
||||
#endif
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class StatusEffect
|
||||
partial class StatusEffect
|
||||
{
|
||||
[Flags]
|
||||
public enum TargetType
|
||||
@@ -20,6 +22,12 @@ namespace Barotrauma
|
||||
|
||||
private List<RelatedItem> requiredItems;
|
||||
|
||||
#if CLIENT
|
||||
private List<ParticleEmitterPrefab> particleEmitters;
|
||||
|
||||
private Sound sound;
|
||||
#endif
|
||||
|
||||
public string[] propertyNames;
|
||||
private object[] propertyEffects;
|
||||
|
||||
@@ -37,12 +45,8 @@ namespace Barotrauma
|
||||
|
||||
private Explosion explosion;
|
||||
|
||||
private List<ParticleEmitterPrefab> particleEmitters;
|
||||
|
||||
public readonly float FireSize;
|
||||
|
||||
private Sound sound;
|
||||
|
||||
public TargetType Targets
|
||||
{
|
||||
get { return targetTypes; }
|
||||
@@ -71,7 +75,10 @@ namespace Barotrauma
|
||||
protected StatusEffect(XElement element)
|
||||
{
|
||||
requiredItems = new List<RelatedItem>();
|
||||
|
||||
#if CLIENT
|
||||
particleEmitters = new List<ParticleEmitterPrefab>();
|
||||
#endif
|
||||
|
||||
IEnumerable<XAttribute> attributes = element.Attributes();
|
||||
List<XAttribute> propertyAttributes = new List<XAttribute>();
|
||||
@@ -122,12 +129,14 @@ namespace Barotrauma
|
||||
targetNames.Add(names[i].Trim());
|
||||
}
|
||||
break;
|
||||
case "sound":
|
||||
sound = Sound.Load(attribute.Value.ToString());
|
||||
break;
|
||||
case "duration":
|
||||
duration = ToolBox.GetAttributeFloat(attribute, 0.0f);
|
||||
break;
|
||||
#if CLIENT
|
||||
case "sound":
|
||||
sound = Sound.Load(attribute.Value.ToString());
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
propertyAttributes.Add(attribute);
|
||||
break;
|
||||
@@ -160,9 +169,6 @@ namespace Barotrauma
|
||||
case "useitem":
|
||||
useItem = true;
|
||||
break;
|
||||
case "particleemitter":
|
||||
particleEmitters.Add(new ParticleEmitterPrefab(subElement));
|
||||
break;
|
||||
case "requireditem":
|
||||
case "requireditems":
|
||||
RelatedItem newRequiredItem = RelatedItem.Load(subElement);
|
||||
@@ -171,6 +177,11 @@ namespace Barotrauma
|
||||
|
||||
requiredItems.Add(newRequiredItem);
|
||||
break;
|
||||
#if CLIENT
|
||||
case "particleemitter":
|
||||
particleEmitters.Add(new ParticleEmitterPrefab(subElement));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,8 +225,10 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
protected void Apply(float deltaTime, Entity entity, List<IPropertyObject> targets)
|
||||
{
|
||||
{
|
||||
#if CLIENT
|
||||
if (sound != null) sound.Play(1.0f, 1000.0f, entity.WorldPosition);
|
||||
#endif
|
||||
|
||||
if (useItem)
|
||||
{
|
||||
@@ -264,12 +277,14 @@ namespace Barotrauma
|
||||
var fire = new FireSource(entity.WorldPosition, hull);
|
||||
|
||||
fire.Size = new Vector2(FireSize, fire.Size.Y);
|
||||
}
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
foreach (ParticleEmitterPrefab emitter in particleEmitters)
|
||||
{
|
||||
emitter.Emit(entity.WorldPosition, hull);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private IEnumerable<object> ApplyToPropertyOverDuration(float duration, ObjectProperty property, object value)
|
||||
|
||||
@@ -27,152 +27,12 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
static class DebugConsole
|
||||
static partial class DebugConsole
|
||||
{
|
||||
const int MaxMessages = 200;
|
||||
|
||||
public static List<ColoredText> Messages = new List<ColoredText>();
|
||||
|
||||
static bool isOpen;
|
||||
|
||||
|
||||
static GUIFrame frame;
|
||||
static GUIListBox listBox;
|
||||
static GUITextBox textBox;
|
||||
|
||||
//used for keeping track of the message entered when pressing up/down
|
||||
static int selectedIndex;
|
||||
|
||||
public static bool IsOpen
|
||||
{
|
||||
get
|
||||
{
|
||||
return isOpen;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Init(GameWindow window)
|
||||
{
|
||||
int x = 20, y = 20;
|
||||
int width = 800, height = 500;
|
||||
|
||||
frame = new GUIFrame(new Rectangle(x, y, width, height), new Color(0.4f, 0.4f, 0.4f, 0.8f));
|
||||
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
|
||||
listBox = new GUIListBox(new Rectangle(0, 0, 0, frame.Rect.Height - 40), Color.Black, "", frame);
|
||||
//listBox.Color = Color.Black * 0.7f;
|
||||
|
||||
textBox = new GUITextBox(new Rectangle(0,0,0,20), Color.Black, Color.White, Alignment.BottomLeft, Alignment.Left, "", frame);
|
||||
//textBox.Color = Color.Black * 0.7f;
|
||||
|
||||
//messages already added before initialization -> add them to the listbox
|
||||
List<ColoredText> unInitializedMessages = new List<ColoredText>(Messages);
|
||||
Messages.Clear();
|
||||
|
||||
foreach (ColoredText msg in unInitializedMessages)
|
||||
{
|
||||
NewMessage(msg.Text, msg.Color);
|
||||
}
|
||||
|
||||
NewMessage("Press F3 to open/close the debug console", Color.Cyan);
|
||||
NewMessage("Enter \"help\" for a list of available console commands", Color.Cyan);
|
||||
|
||||
}
|
||||
|
||||
public static void AddToGUIUpdateList()
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
frame.AddToGUIUpdateList();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Update(GameMain game, float deltaTime)
|
||||
{
|
||||
if (PlayerInput.KeyHit(Keys.F3))
|
||||
{
|
||||
isOpen = !isOpen;
|
||||
if (isOpen)
|
||||
{
|
||||
textBox.Select();
|
||||
AddToGUIUpdateList();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIComponent.ForceMouseOn(null);
|
||||
textBox.Deselect();
|
||||
}
|
||||
|
||||
//keyboardDispatcher.Subscriber = (isOpen) ? textBox : null;
|
||||
}
|
||||
|
||||
if (isOpen)
|
||||
{
|
||||
frame.Update(deltaTime);
|
||||
|
||||
Character.DisableControls = true;
|
||||
|
||||
if (PlayerInput.KeyHit(Keys.Up))
|
||||
{
|
||||
SelectMessage(-1);
|
||||
}
|
||||
else if (PlayerInput.KeyHit(Keys.Down))
|
||||
{
|
||||
SelectMessage(1);
|
||||
}
|
||||
|
||||
//textBox.Update(deltaTime);
|
||||
|
||||
if (PlayerInput.KeyDown(Keys.Enter) && textBox.Text != "")
|
||||
{
|
||||
ExecuteCommand(textBox.Text, game);
|
||||
textBox.Text = "";
|
||||
|
||||
//selectedIndex = messages.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void SelectMessage(int direction)
|
||||
{
|
||||
int messageCount = listBox.children.Count;
|
||||
if (messageCount == 0) return;
|
||||
|
||||
direction = Math.Min(Math.Max(-1, direction), 1);
|
||||
|
||||
selectedIndex += direction;
|
||||
if (selectedIndex < 0) selectedIndex = messageCount - 1;
|
||||
selectedIndex = selectedIndex % messageCount;
|
||||
|
||||
textBox.Text = (listBox.children[selectedIndex] as GUITextBlock).Text;
|
||||
}
|
||||
|
||||
public static void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
if (!isOpen) return;
|
||||
|
||||
frame.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
private static bool IsCommandPermitted(string command, GameClient client)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case "kick":
|
||||
return client.HasPermission(ClientPermissions.Kick);
|
||||
case "ban":
|
||||
case "banip":
|
||||
return client.HasPermission(ClientPermissions.Ban);
|
||||
case "netstats":
|
||||
case "help":
|
||||
case "dumpids":
|
||||
case "admin":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteCommand(string command, GameMain game)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(command)) return;
|
||||
@@ -180,15 +40,17 @@ namespace Barotrauma
|
||||
|
||||
if (!commands[0].ToLowerInvariant().Equals("admin"))
|
||||
{
|
||||
NewMessage(textBox.Text, Color.White);
|
||||
NewMessage(InputText, Color.White);
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null && !IsCommandPermitted(commands[0].ToLowerInvariant(), GameMain.Client))
|
||||
{
|
||||
ThrowError("You're not permitted to use the command \"" + commands[0].ToLowerInvariant()+"\"!");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
switch (commands[0].ToLowerInvariant())
|
||||
@@ -304,8 +166,9 @@ namespace Barotrauma
|
||||
|
||||
if (commands[1].ToLowerInvariant()=="human")
|
||||
{
|
||||
spawnedCharacter = Character.Create(Character.HumanConfigFile, spawnPosition);
|
||||
spawnedCharacter = Character.Create(Character.HumanConfigFile, spawnPosition);
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession != null)
|
||||
{
|
||||
SinglePlayerMode mode = GameMain.GameSession.gameMode as SinglePlayerMode;
|
||||
@@ -316,6 +179,7 @@ namespace Barotrauma
|
||||
GameMain.GameSession.CrewManager.SelectCharacter(null, Character.Controlled);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -418,90 +282,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "startclient":
|
||||
if (commands.Length == 1) return;
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
GameMain.NetworkMember = new GameClient("Name");
|
||||
GameMain.Client.ConnectToServer(commands[1]);
|
||||
}
|
||||
break;
|
||||
case "mainmenuscreen":
|
||||
case "mainmenu":
|
||||
case "menu":
|
||||
GameMain.GameSession = null;
|
||||
|
||||
List<Character> characters = new List<Character>(Character.CharacterList);
|
||||
foreach (Character c in characters)
|
||||
{
|
||||
c.Remove();
|
||||
}
|
||||
|
||||
GameMain.MainMenuScreen.Select();
|
||||
break;
|
||||
case "gamescreen":
|
||||
case "game":
|
||||
GameMain.GameScreen.Select();
|
||||
break;
|
||||
case "editmapscreen":
|
||||
case "editmap":
|
||||
case "edit":
|
||||
if (commands.Length>1)
|
||||
{
|
||||
Submarine.Load(string.Join(" ", commands.Skip(1)), true);
|
||||
}
|
||||
GameMain.EditMapScreen.Select();
|
||||
break;
|
||||
case "test":
|
||||
Submarine.Load("aegir mark ii", true);
|
||||
GameMain.DebugDraw = true;
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
GameMain.EditMapScreen.Select();
|
||||
break;
|
||||
case "editcharacter":
|
||||
case "editchar":
|
||||
GameMain.EditCharacterScreen.Select();
|
||||
break;
|
||||
case "controlcharacter":
|
||||
case "control":
|
||||
{
|
||||
if (commands.Length < 2) break;
|
||||
|
||||
var character = FindMatchingCharacter(commands, true);
|
||||
|
||||
if (character != null)
|
||||
{
|
||||
Character.Controlled = character;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "setclientcharacter":
|
||||
{
|
||||
if (GameMain.Server == null) break;
|
||||
|
||||
int separatorIndex = Array.IndexOf(commands, ";");
|
||||
|
||||
if (separatorIndex == -1 || commands.Length < 4)
|
||||
{
|
||||
ThrowError("Invalid parameters. The command should be formatted as \"setclientcharacter [client] ; [character]\"");
|
||||
break;
|
||||
}
|
||||
|
||||
string[] commandsLeft = commands.Take(separatorIndex).ToArray();
|
||||
string[] commandsRight = commands.Skip(separatorIndex).ToArray();
|
||||
|
||||
string clientName = String.Join(" ", commandsLeft.Skip(1));
|
||||
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.name == clientName);
|
||||
if (client == null)
|
||||
{
|
||||
ThrowError("Client \"" + clientName + "\" not found.");
|
||||
}
|
||||
|
||||
var character = FindMatchingCharacter(commandsRight, false);
|
||||
GameMain.Server.SetClientCharacter(client, character);
|
||||
}
|
||||
break;
|
||||
case "teleportcharacter":
|
||||
case "teleport":
|
||||
var tpCharacter = FindMatchingCharacter(commands, false);
|
||||
@@ -638,20 +418,6 @@ namespace Barotrauma
|
||||
reactorItem.CreateServerEvent(reactor);
|
||||
}
|
||||
break;
|
||||
case "shake":
|
||||
GameMain.GameScreen.Cam.Shake = 10.0f;
|
||||
break;
|
||||
case "losenabled":
|
||||
case "los":
|
||||
case "drawlos":
|
||||
GameMain.LightManager.LosEnabled = !GameMain.LightManager.LosEnabled;
|
||||
break;
|
||||
case "lighting":
|
||||
case "lightingenabled":
|
||||
case "light":
|
||||
case "lights":
|
||||
GameMain.LightManager.LightingEnabled = !GameMain.LightManager.LightingEnabled;
|
||||
break;
|
||||
case "oxygen":
|
||||
case "air":
|
||||
foreach (Hull hull in Hull.hullList)
|
||||
@@ -659,99 +425,7 @@ namespace Barotrauma
|
||||
hull.OxygenPercentage = 100.0f;
|
||||
}
|
||||
break;
|
||||
case "tutorial":
|
||||
TutorialMode.StartTutorial(Tutorials.TutorialType.TutorialTypes[0]);
|
||||
|
||||
|
||||
break;
|
||||
case "editortutorial":
|
||||
GameMain.EditMapScreen.Select();
|
||||
GameMain.EditMapScreen.StartTutorial();
|
||||
break;
|
||||
case "lobbyscreen":
|
||||
case "lobby":
|
||||
GameMain.LobbyScreen.Select();
|
||||
break;
|
||||
case "savemap":
|
||||
case "savesub":
|
||||
case "save":
|
||||
if (commands.Length < 2) break;
|
||||
|
||||
if (GameMain.EditMapScreen.CharacterMode)
|
||||
{
|
||||
GameMain.EditMapScreen.ToggleCharacterMode();
|
||||
}
|
||||
|
||||
string fileName = string.Join(" ", commands.Skip(1));
|
||||
if (fileName.Contains("../"))
|
||||
{
|
||||
DebugConsole.ThrowError("Illegal symbols in filename (../)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Submarine.SaveCurrent(System.IO.Path.Combine(Submarine.SavePath, fileName + ".sub")))
|
||||
{
|
||||
NewMessage("Sub saved", Color.Green);
|
||||
//Submarine.Loaded.First().CheckForErrors();
|
||||
}
|
||||
|
||||
break;
|
||||
case "loadmap":
|
||||
case "loadsub":
|
||||
case "load":
|
||||
if (commands.Length < 2) break;
|
||||
|
||||
Submarine.Load(string.Join(" ", commands.Skip(1)), true);
|
||||
break;
|
||||
case "cleansub":
|
||||
for (int i = MapEntity.mapEntityList.Count - 1; i >= 0; i--)
|
||||
{
|
||||
MapEntity me = MapEntity.mapEntityList[i];
|
||||
|
||||
if (me.SimPosition.Length()>2000.0f)
|
||||
{
|
||||
DebugConsole.NewMessage("Removed "+me.Name+" (simposition "+me.SimPosition+")", Color.Orange);
|
||||
MapEntity.mapEntityList.RemoveAt(i);
|
||||
}
|
||||
else if (me.MoveWithLevel)
|
||||
{
|
||||
DebugConsole.NewMessage("Removed " + me.Name + " (MoveWithLevel==true)", Color.Orange);
|
||||
MapEntity.mapEntityList.RemoveAt(i);
|
||||
}
|
||||
else if (me is Item)
|
||||
{
|
||||
Item item = me as Item;
|
||||
var wire = item.GetComponent<Wire>();
|
||||
if (wire == null) continue;
|
||||
|
||||
if (wire.GetNodes().Count > 0 && !wire.Connections.Any(c => c != null))
|
||||
{
|
||||
wire.Item.Drop(null);
|
||||
DebugConsole.NewMessage("Dropped wire (ID: "+wire.Item.ID+") - attached on wall but no connections found", Color.Orange);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case "messagebox":
|
||||
if (commands.Length < 3) break;
|
||||
new GUIMessageBox(commands[1], commands[2]);
|
||||
break;
|
||||
case "debugdraw":
|
||||
GameMain.DebugDraw = !GameMain.DebugDraw;
|
||||
break;
|
||||
case "disablehud":
|
||||
case "hud":
|
||||
GUI.DisableHUD = !GUI.DisableHUD;
|
||||
GameMain.Instance.IsMouseVisible = !GameMain.Instance.IsMouseVisible;
|
||||
break;
|
||||
case "followsub":
|
||||
Camera.FollowSub = !Camera.FollowSub;
|
||||
break;
|
||||
case "drawaitargets":
|
||||
case "showaitargets":
|
||||
AITarget.ShowAITargets = !AITarget.ShowAITargets;
|
||||
break;
|
||||
|
||||
case "killmonsters":
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
@@ -764,143 +438,9 @@ namespace Barotrauma
|
||||
|
||||
GameMain.Server.ShowNetStats = !GameMain.Server.ShowNetStats;
|
||||
break;
|
||||
#if DEBUG
|
||||
case "spamevents":
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
for (int i = 0; i<item.components.Count; i++)
|
||||
{
|
||||
if (item.components[i] is IServerSerializable)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, i });
|
||||
}
|
||||
var itemContainer = item.GetComponent<ItemContainer>();
|
||||
if (itemContainer != null)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.InventoryState });
|
||||
}
|
||||
|
||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status });
|
||||
|
||||
item.NeedsPositionUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(c, new object[] { NetEntityEvent.Type.Status });
|
||||
}
|
||||
|
||||
foreach (Structure wall in Structure.WallList)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(wall);
|
||||
}
|
||||
break;
|
||||
case "spamchatmessages":
|
||||
int msgCount = 1000;
|
||||
if (commands.Length > 1) int.TryParse(commands[1], out msgCount);
|
||||
int msgLength = 50;
|
||||
if (commands.Length > 2) int.TryParse(commands[2], out msgLength);
|
||||
|
||||
for (int i = 0; i < msgCount; i++)
|
||||
{
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
GameMain.Server.SendChatMessage(ToolBox.RandomSeed(msgLength), ChatMessageType.Default);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Client.SendChatMessage(ToolBox.RandomSeed(msgLength));
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case "cleanbuild":
|
||||
GameMain.Config.MusicVolume = 0.5f;
|
||||
GameMain.Config.SoundVolume = 0.5f;
|
||||
DebugConsole.NewMessage("Music and sound volume set to 0.5", Color.Green);
|
||||
|
||||
GameMain.Config.GraphicsWidth = 0;
|
||||
GameMain.Config.GraphicsHeight = 0;
|
||||
GameMain.Config.WindowMode = WindowMode.Fullscreen;
|
||||
DebugConsole.NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
|
||||
DebugConsole.NewMessage("Fullscreen enabled", Color.Green);
|
||||
|
||||
GameSettings.VerboseLogging = false;
|
||||
|
||||
if (GameMain.Config.MasterServerUrl != "http://www.undertowgames.com/baromaster")
|
||||
{
|
||||
DebugConsole.ThrowError("MasterServerUrl \""+GameMain.Config.MasterServerUrl+"\"!");
|
||||
}
|
||||
|
||||
GameMain.Config.Save("config.xml");
|
||||
|
||||
var saveFiles = System.IO.Directory.GetFiles(SaveUtil.SaveFolder);
|
||||
|
||||
foreach (string saveFile in saveFiles)
|
||||
{
|
||||
System.IO.File.Delete(saveFile);
|
||||
DebugConsole.NewMessage("Deleted "+saveFile, Color.Green);
|
||||
}
|
||||
|
||||
if (System.IO.Directory.Exists(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp")))
|
||||
{
|
||||
System.IO.Directory.Delete(System.IO.Path.Combine(SaveUtil.SaveFolder, "temp"), true);
|
||||
DebugConsole.NewMessage("Deleted temp save folder", Color.Green);
|
||||
}
|
||||
|
||||
if (System.IO.Directory.Exists(ServerLog.SavePath))
|
||||
{
|
||||
var logFiles = System.IO.Directory.GetFiles(ServerLog.SavePath);
|
||||
|
||||
foreach (string logFile in logFiles)
|
||||
{
|
||||
System.IO.File.Delete(logFile);
|
||||
DebugConsole.NewMessage("Deleted "+logFile, Color.Green);
|
||||
}
|
||||
}
|
||||
|
||||
if (System.IO.File.Exists("filelist.xml"))
|
||||
{
|
||||
System.IO.File.Delete("filelist.xml");
|
||||
DebugConsole.NewMessage("Deleted filelist", Color.Green);
|
||||
}
|
||||
|
||||
|
||||
if (System.IO.File.Exists("Submarines/TutorialSub.sub"))
|
||||
{
|
||||
System.IO.File.Delete("Submarines/TutorialSub.sub");
|
||||
|
||||
DebugConsole.NewMessage("Deleted TutorialSub from the submarine folder", Color.Green);
|
||||
}
|
||||
|
||||
if (System.IO.File.Exists(GameServer.SettingsFile))
|
||||
{
|
||||
System.IO.File.Delete(GameServer.SettingsFile);
|
||||
DebugConsole.NewMessage("Deleted server settings", Color.Green);
|
||||
}
|
||||
|
||||
if (System.IO.File.Exists(GameServer.ClientPermissionsFile))
|
||||
{
|
||||
System.IO.File.Delete(GameServer.ClientPermissionsFile);
|
||||
DebugConsole.NewMessage("Deleted client permission file", Color.Green);
|
||||
|
||||
}
|
||||
|
||||
if (System.IO.File.Exists("crashreport.txt"))
|
||||
{
|
||||
System.IO.File.Delete("crashreport.txt");
|
||||
DebugConsole.NewMessage("Deleted crashreport.txt", Color.Green);
|
||||
}
|
||||
|
||||
if (!System.IO.File.Exists("Content/Map/TutorialSub.sub"))
|
||||
{
|
||||
DebugConsole.ThrowError("TutorialSub.sub not found!");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
NewMessage("Command not found", Color.Red);
|
||||
if (!ExecProjSpecific(commands)) NewMessage("Command not found", Color.Red);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -963,6 +503,7 @@ namespace Barotrauma
|
||||
Messages.RemoveRange(0, Messages.Count - MaxMessages);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
//listbox not created yet, don't attempt to add
|
||||
if (listBox == null) return;
|
||||
|
||||
@@ -986,6 +527,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
selectedIndex = listBox.children.Count;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void Log(string message)
|
||||
@@ -1001,7 +543,9 @@ namespace Barotrauma
|
||||
}
|
||||
System.Diagnostics.Debug.WriteLine(error);
|
||||
NewMessage(error, Color.Red);
|
||||
#if CLIENT
|
||||
isOpen = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,359 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,411 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,674 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class GameSession
|
||||
partial class GameSession
|
||||
{
|
||||
public enum InfoFrameTab { Crew, Mission, ManagePlayers };
|
||||
|
||||
@@ -16,17 +16,13 @@ namespace Barotrauma
|
||||
//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;
|
||||
|
||||
#if CLIENT
|
||||
public CrewManager CrewManager;
|
||||
|
||||
private ShiftSummary shiftSummary;
|
||||
#endif
|
||||
|
||||
private Mission currentMission;
|
||||
|
||||
@@ -44,16 +40,7 @@ namespace Barotrauma
|
||||
{
|
||||
get { return level; }
|
||||
}
|
||||
|
||||
public Map Map
|
||||
{
|
||||
get
|
||||
{
|
||||
SinglePlayerMode mode = (gameMode as SinglePlayerMode);
|
||||
return (mode == null) ? null : mode.Map;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Location StartLocation
|
||||
{
|
||||
get
|
||||
@@ -94,26 +81,23 @@ namespace Barotrauma
|
||||
{
|
||||
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;
|
||||
|
||||
#if CLIENT
|
||||
CrewManager = new CrewManager();
|
||||
|
||||
infoButton = new GUIButton(new Rectangle(10, 10, 100, 20), "Info", "", null);
|
||||
infoButton.OnClicked = ToggleInfoFrame;
|
||||
#endif
|
||||
|
||||
if (gameModePreset != null) gameMode = gameModePreset.Instantiate(missionType);
|
||||
this.submarine = submarine;
|
||||
@@ -125,17 +109,19 @@ namespace Barotrauma
|
||||
Submarine.MainSub = submarine;
|
||||
|
||||
GameMain.GameSession = this;
|
||||
|
||||
CrewManager = new CrewManager();
|
||||
|
||||
|
||||
selectedSub.Name = ToolBox.GetAttributeString(doc.Root, "submarine", selectedSub.Name);
|
||||
|
||||
#if CLIENT
|
||||
CrewManager = new CrewManager();
|
||||
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "gamemode") continue;
|
||||
|
||||
gameMode = new SinglePlayerMode(subElement);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void CreateDummyLocations()
|
||||
@@ -168,7 +154,9 @@ namespace Barotrauma
|
||||
|
||||
public void StartShift(Level level, bool reloadSub = true, bool loadSecondSub = false)
|
||||
{
|
||||
#if CLIENT
|
||||
GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
|
||||
#endif
|
||||
|
||||
this.level = level;
|
||||
|
||||
@@ -198,8 +186,10 @@ namespace Barotrauma
|
||||
level.Generate();
|
||||
|
||||
submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
|
||||
|
||||
|
||||
#if CLIENT
|
||||
GameMain.GameScreen.BackgroundCreatureManager.SpawnSprites(80);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (gameMode.Mission != null)
|
||||
@@ -207,8 +197,6 @@ namespace Barotrauma
|
||||
currentMission = gameMode.Mission;
|
||||
}
|
||||
|
||||
shiftSummary = new ShiftSummary(this);
|
||||
|
||||
if (gameMode!=null) gameMode.Start();
|
||||
|
||||
if (gameMode.Mission != null) Mission.Start(Level.Loaded);
|
||||
@@ -219,8 +207,12 @@ namespace Barotrauma
|
||||
|
||||
Entity.Spawner = new EntitySpawner();
|
||||
|
||||
#if CLIENT
|
||||
shiftSummary = new ShiftSummary(this);
|
||||
|
||||
GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);
|
||||
SoundPlayer.SwitchMusic();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void EndShift(string endMessage)
|
||||
@@ -238,6 +230,7 @@ namespace Barotrauma
|
||||
GameMain.LobbyScreen.Select();
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (shiftSummary != null)
|
||||
{
|
||||
GUIFrame summaryFrame = shiftSummary.CreateSummaryFrame(endMessage);
|
||||
@@ -245,6 +238,7 @@ namespace Barotrauma
|
||||
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; };
|
||||
}
|
||||
#endif
|
||||
|
||||
TaskManager.EndShift();
|
||||
|
||||
@@ -253,182 +247,19 @@ namespace Barotrauma
|
||||
StatusEffect.StopAll();
|
||||
}
|
||||
|
||||
|
||||
public void KillCharacter(Character character)
|
||||
{
|
||||
#if CLIENT
|
||||
CrewManager.KillCharacter(character);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ReviveCharacter(Character character)
|
||||
{
|
||||
#if CLIENT
|
||||
CrewManager.ReviveCharacter(character);
|
||||
#endif
|
||||
}
|
||||
|
||||
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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -9,51 +7,10 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public enum WindowMode
|
||||
|
||||
public partial class GameSettings
|
||||
{
|
||||
Windowed, Fullscreen, BorderlessWindowed
|
||||
}
|
||||
|
||||
public class GameSettings
|
||||
{
|
||||
private GUIFrame settingsFrame;
|
||||
private GUIButton applyButton;
|
||||
|
||||
private float soundVolume, musicVolume;
|
||||
|
||||
private WindowMode windowMode;
|
||||
|
||||
private KeyOrMouse[] keyMapping;
|
||||
|
||||
private bool unsavedSettings;
|
||||
|
||||
public GUIFrame SettingsFrame
|
||||
{
|
||||
get
|
||||
{
|
||||
if (settingsFrame == null) CreateSettingsFrame();
|
||||
return settingsFrame;
|
||||
}
|
||||
}
|
||||
|
||||
public KeyOrMouse KeyBind(InputType inputType)
|
||||
{
|
||||
return keyMapping[(int)inputType];
|
||||
}
|
||||
|
||||
public int GraphicsWidth { get; set; }
|
||||
public int GraphicsHeight { get; set; }
|
||||
|
||||
public bool VSyncEnabled { get; set; }
|
||||
|
||||
//public bool FullScreenEnabled { get; set; }
|
||||
|
||||
public WindowMode WindowMode
|
||||
{
|
||||
get { return windowMode; }
|
||||
set { windowMode = value; }
|
||||
}
|
||||
|
||||
|
||||
public ContentPackage SelectedContentPackage { get; set; }
|
||||
|
||||
public string MasterServerUrl { get; set; }
|
||||
@@ -62,46 +19,6 @@ namespace Barotrauma
|
||||
|
||||
public static bool VerboseLogging { get; set; }
|
||||
|
||||
public bool EnableSplashScreen { get; set; }
|
||||
|
||||
public bool UnsavedSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
return unsavedSettings;
|
||||
}
|
||||
private set
|
||||
{
|
||||
unsavedSettings = value;
|
||||
if (applyButton != null)
|
||||
{
|
||||
//applyButton.Selected = unsavedSettings;
|
||||
applyButton.Enabled = unsavedSettings;
|
||||
applyButton.Text = unsavedSettings ? "Apply*" : "Apply";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float SoundVolume
|
||||
{
|
||||
get { return soundVolume; }
|
||||
set
|
||||
{
|
||||
soundVolume = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||
Sounds.SoundManager.MasterVolume = soundVolume;
|
||||
}
|
||||
}
|
||||
|
||||
public float MusicVolume
|
||||
{
|
||||
get { return musicVolume; }
|
||||
set
|
||||
{
|
||||
musicVolume = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||
SoundPlayer.MusicVolume = musicVolume;
|
||||
}
|
||||
}
|
||||
|
||||
public GameSettings(string filePath)
|
||||
{
|
||||
ContentPackage.LoadAll(ContentPackage.Folder);
|
||||
@@ -117,9 +34,6 @@ namespace Barotrauma
|
||||
{
|
||||
DebugConsole.ThrowError("No config file found");
|
||||
|
||||
GraphicsWidth = 1024;
|
||||
GraphicsHeight = 678;
|
||||
|
||||
MasterServerUrl = "";
|
||||
|
||||
SelectedContentPackage = ContentPackage.list.Any() ? ContentPackage.list[0] : new ContentPackage("");
|
||||
@@ -127,53 +41,15 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
XElement graphicsMode = doc.Root.Element("graphicsmode");
|
||||
GraphicsWidth = ToolBox.GetAttributeInt(graphicsMode, "width", 0);
|
||||
GraphicsHeight = ToolBox.GetAttributeInt(graphicsMode, "height", 0);
|
||||
VSyncEnabled = ToolBox.GetAttributeBool(graphicsMode, "vsync", true);
|
||||
|
||||
if (GraphicsWidth==0 || GraphicsHeight==0)
|
||||
{
|
||||
GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
|
||||
GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
|
||||
}
|
||||
|
||||
//FullScreenEnabled = ToolBox.GetAttributeBool(graphicsMode, "fullscreen", true);
|
||||
|
||||
var windowModeStr = ToolBox.GetAttributeString(graphicsMode, "displaymode", "Fullscreen");
|
||||
if (!Enum.TryParse<WindowMode>(windowModeStr, out windowMode))
|
||||
{
|
||||
windowMode = WindowMode.Fullscreen;
|
||||
}
|
||||
|
||||
MasterServerUrl = ToolBox.GetAttributeString(doc.Root, "masterserverurl", "");
|
||||
|
||||
AutoCheckUpdates = ToolBox.GetAttributeBool(doc.Root, "autocheckupdates", true);
|
||||
WasGameUpdated = ToolBox.GetAttributeBool(doc.Root, "wasgameupdated", false);
|
||||
|
||||
SoundVolume = ToolBox.GetAttributeFloat(doc.Root, "soundvolume", 1.0f);
|
||||
MusicVolume = ToolBox.GetAttributeFloat(doc.Root, "musicvolume", 0.3f);
|
||||
|
||||
VerboseLogging = ToolBox.GetAttributeBool(doc.Root, "verboselogging", false);
|
||||
|
||||
EnableSplashScreen = ToolBox.GetAttributeBool(doc.Root, "enablesplashscreen", true);
|
||||
InitProjSpecific(doc);
|
||||
|
||||
keyMapping = new KeyOrMouse[Enum.GetNames(typeof(InputType)).Length];
|
||||
keyMapping[(int)InputType.Up] = new KeyOrMouse(Keys.W);
|
||||
keyMapping[(int)InputType.Down] = new KeyOrMouse(Keys.S);
|
||||
keyMapping[(int)InputType.Left] = new KeyOrMouse(Keys.A);
|
||||
keyMapping[(int)InputType.Right] = new KeyOrMouse(Keys.D);
|
||||
keyMapping[(int)InputType.Run] = new KeyOrMouse(Keys.LeftShift);
|
||||
|
||||
|
||||
keyMapping[(int)InputType.Chat] = new KeyOrMouse(Keys.Tab);
|
||||
keyMapping[(int)InputType.CrewOrders] = new KeyOrMouse(Keys.C);
|
||||
|
||||
keyMapping[(int)InputType.Select] = new KeyOrMouse(Keys.E);
|
||||
|
||||
keyMapping[(int)InputType.Use] = new KeyOrMouse(0);
|
||||
keyMapping[(int)InputType.Aim] = new KeyOrMouse(1);
|
||||
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -186,332 +62,9 @@ namespace Barotrauma
|
||||
|
||||
if (SelectedContentPackage == null) SelectedContentPackage = new ContentPackage(path);
|
||||
break;
|
||||
case "keymapping":
|
||||
foreach (XAttribute attribute in subElement.Attributes())
|
||||
{
|
||||
InputType inputType;
|
||||
if (Enum.TryParse(attribute.Name.ToString(), true, out inputType))
|
||||
{
|
||||
int mouseButton;
|
||||
if (int.TryParse(attribute.Value.ToString(), out mouseButton))
|
||||
{
|
||||
keyMapping[(int)inputType] = new KeyOrMouse(mouseButton);
|
||||
}
|
||||
else
|
||||
{
|
||||
Keys key;
|
||||
if (Enum.TryParse(attribute.Value.ToString(), true, out key))
|
||||
{
|
||||
keyMapping[(int)inputType] = new KeyOrMouse(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (InputType inputType in Enum.GetValues(typeof(InputType)))
|
||||
{
|
||||
if (keyMapping[(int)inputType]==null)
|
||||
{
|
||||
DebugConsole.ThrowError("Key binding for the input type \"" + inputType + " not set!");
|
||||
keyMapping[(int)inputType] = new KeyOrMouse(Keys.D1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UnsavedSettings = false;
|
||||
}
|
||||
|
||||
public void Save(string filePath)
|
||||
{
|
||||
UnsavedSettings = false;
|
||||
|
||||
XDocument doc = new XDocument();
|
||||
|
||||
if (doc.Root == null)
|
||||
{
|
||||
doc.Add(new XElement("config"));
|
||||
}
|
||||
|
||||
doc.Root.Add(
|
||||
new XAttribute("masterserverurl", MasterServerUrl),
|
||||
new XAttribute("autocheckupdates", AutoCheckUpdates),
|
||||
new XAttribute("musicvolume", musicVolume),
|
||||
new XAttribute("soundvolume", soundVolume),
|
||||
new XAttribute("verboselogging", VerboseLogging),
|
||||
new XAttribute("enablesplashscreen", EnableSplashScreen));
|
||||
|
||||
if (WasGameUpdated)
|
||||
{
|
||||
doc.Root.Add(new XAttribute("wasgameupdated", true));
|
||||
}
|
||||
|
||||
XElement gMode = doc.Root.Element("graphicsmode");
|
||||
if (gMode == null)
|
||||
{
|
||||
gMode = new XElement("graphicsmode");
|
||||
doc.Root.Add(gMode);
|
||||
}
|
||||
|
||||
if (GraphicsWidth==0 || GraphicsHeight==0)
|
||||
{
|
||||
gMode.ReplaceAttributes(new XAttribute("displaymode", windowMode));
|
||||
}
|
||||
else
|
||||
{
|
||||
gMode.ReplaceAttributes(
|
||||
new XAttribute("width", GraphicsWidth),
|
||||
new XAttribute("height", GraphicsHeight),
|
||||
new XAttribute("vsync", VSyncEnabled),
|
||||
new XAttribute("displaymode", windowMode));
|
||||
}
|
||||
|
||||
|
||||
if (SelectedContentPackage != null)
|
||||
{
|
||||
doc.Root.Add(new XElement("contentpackage",
|
||||
new XAttribute("path", SelectedContentPackage.Path)));
|
||||
}
|
||||
|
||||
var keyMappingElement = new XElement("keymapping");
|
||||
doc.Root.Add(keyMappingElement);
|
||||
for (int i = 0; i<keyMapping.Length;i++)
|
||||
{
|
||||
if (keyMapping[i].MouseButton==null)
|
||||
{
|
||||
keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].Key));
|
||||
}
|
||||
else
|
||||
{
|
||||
keyMappingElement.Add(new XAttribute(((InputType)i).ToString(), keyMapping[i].MouseButton));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
doc.Save(filePath);
|
||||
}
|
||||
|
||||
private bool ChangeSoundVolume(GUIScrollBar scrollBar, float barScroll)
|
||||
{
|
||||
UnsavedSettings = true;
|
||||
SoundVolume = barScroll;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ChangeMusicVolume(GUIScrollBar scrollBar, float barScroll)
|
||||
{
|
||||
UnsavedSettings = true;
|
||||
MusicVolume = barScroll;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ResetSettingsFrame()
|
||||
{
|
||||
settingsFrame = null;
|
||||
}
|
||||
|
||||
private void CreateSettingsFrame()
|
||||
{
|
||||
settingsFrame = new GUIFrame(new Rectangle(0, 0, 500, 500), null, Alignment.Center, "");
|
||||
|
||||
new GUITextBlock(new Rectangle(0, -30, 0, 30), "Settings", "", Alignment.TopCenter, Alignment.TopCenter, settingsFrame, false, GUI.LargeFont);
|
||||
|
||||
int x = 0, y = 10;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, y, 20, 20), "Resolution", "", Alignment.TopLeft, Alignment.TopLeft, settingsFrame);
|
||||
var resolutionDD = new GUIDropDown(new Rectangle(0, y + 20, 180, 20), "", "", settingsFrame);
|
||||
resolutionDD.OnSelected = SelectResolution;
|
||||
|
||||
var supportedModes = new List<DisplayMode>();
|
||||
foreach (DisplayMode mode in GraphicsAdapter.DefaultAdapter.SupportedDisplayModes)
|
||||
{
|
||||
if (supportedModes.FirstOrDefault(m => m.Width == mode.Width && m.Height == mode.Height) != null) continue;
|
||||
|
||||
resolutionDD.AddItem(mode.Width + "x" + mode.Height, mode);
|
||||
supportedModes.Add(mode);
|
||||
|
||||
if (GraphicsWidth == mode.Width && GraphicsHeight == mode.Height) resolutionDD.SelectItem(mode);
|
||||
}
|
||||
|
||||
if (resolutionDD.SelectedItemData == null)
|
||||
{
|
||||
resolutionDD.SelectItem(GraphicsAdapter.DefaultAdapter.SupportedDisplayModes.Last());
|
||||
}
|
||||
|
||||
y += 50;
|
||||
|
||||
//var fullScreenTick = new GUITickBox(new Rectangle(x, y, 20, 20), "Fullscreen", Alignment.TopLeft, settingsFrame);
|
||||
//fullScreenTick.OnSelected = ToggleFullScreen;
|
||||
//fullScreenTick.Selected = FullScreenEnabled;
|
||||
|
||||
new GUITextBlock(new Rectangle(x, y, 20, 20), "Display mode", "", Alignment.TopLeft, Alignment.TopLeft, settingsFrame);
|
||||
var displayModeDD = new GUIDropDown(new Rectangle(x, y + 20, 180, 20), "", "", settingsFrame);
|
||||
displayModeDD.AddItem("Fullscreen", WindowMode.Fullscreen);
|
||||
displayModeDD.AddItem("Windowed", WindowMode.Windowed);
|
||||
displayModeDD.AddItem("Borderless windowed", WindowMode.BorderlessWindowed);
|
||||
|
||||
displayModeDD.SelectItem(GameMain.Config.WindowMode);
|
||||
|
||||
displayModeDD.OnSelected = (guiComponent, obj) => { GameMain.Config.WindowMode = (WindowMode)guiComponent.UserData; return true; };
|
||||
|
||||
y += 70;
|
||||
|
||||
GUITickBox vsyncTickBox = new GUITickBox(new Rectangle(0, y, 20, 20), "Enable vertical sync",Alignment.CenterY | Alignment.Left,settingsFrame);
|
||||
vsyncTickBox.OnSelected = (GUITickBox box) =>
|
||||
{
|
||||
VSyncEnabled = !VSyncEnabled;
|
||||
GameMain.GraphicsDeviceManager.SynchronizeWithVerticalRetrace = VSyncEnabled;
|
||||
GameMain.GraphicsDeviceManager.ApplyChanges();
|
||||
UnsavedSettings = true;
|
||||
|
||||
return true;
|
||||
};
|
||||
vsyncTickBox.Selected = VSyncEnabled;
|
||||
|
||||
y += 70;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, y, 100, 20), "Sound volume:", "", settingsFrame);
|
||||
GUIScrollBar soundScrollBar = new GUIScrollBar(new Rectangle(0, y + 20, 150, 20), "", 0.1f, settingsFrame);
|
||||
soundScrollBar.BarScroll = SoundVolume;
|
||||
soundScrollBar.OnMoved = ChangeSoundVolume;
|
||||
soundScrollBar.Step = 0.05f;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, y + 40, 100, 20), "Music volume:", "", settingsFrame);
|
||||
GUIScrollBar musicScrollBar = new GUIScrollBar(new Rectangle(0, y + 60, 150, 20), "", 0.1f, settingsFrame);
|
||||
musicScrollBar.BarScroll = MusicVolume;
|
||||
musicScrollBar.OnMoved = ChangeMusicVolume;
|
||||
musicScrollBar.Step = 0.05f;
|
||||
|
||||
x = 200;
|
||||
y = 10;
|
||||
|
||||
new GUITextBlock(new Rectangle(x, y, 20, 20), "Content package", "", Alignment.TopLeft, Alignment.TopLeft, settingsFrame);
|
||||
var contentPackageDD = new GUIDropDown(new Rectangle(x, y + 20, 200, 20), "", "", settingsFrame);
|
||||
|
||||
foreach (ContentPackage contentPackage in ContentPackage.list)
|
||||
{
|
||||
contentPackageDD.AddItem(contentPackage.Name, contentPackage);
|
||||
|
||||
if (SelectedContentPackage == contentPackage) contentPackageDD.SelectItem(contentPackage);
|
||||
}
|
||||
|
||||
y += 50;
|
||||
new GUITextBlock(new Rectangle(x, y, 100, 20), "Controls:", "", settingsFrame);
|
||||
y += 30;
|
||||
var inputNames = Enum.GetNames(typeof(InputType));
|
||||
for (int i = 0; i< inputNames.Length; i++)
|
||||
{
|
||||
new GUITextBlock(new Rectangle(x, y, 100, 18), inputNames[i]+": ", "", Alignment.TopLeft, Alignment.CenterLeft, settingsFrame);
|
||||
var keyBox = new GUITextBox(new Rectangle(x + 100, y, 120, 18), null,null, Alignment.TopLeft, Alignment.CenterLeft, "", settingsFrame);
|
||||
|
||||
keyBox.Text = keyMapping[i].ToString();
|
||||
keyBox.UserData = i;
|
||||
keyBox.OnSelected += KeyBoxSelected;
|
||||
keyBox.SelectedColor = Color.Gold * 0.3f;
|
||||
|
||||
y += 20;
|
||||
}
|
||||
|
||||
applyButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Apply", Alignment.BottomRight, "", settingsFrame);
|
||||
applyButton.OnClicked = ApplyClicked;
|
||||
}
|
||||
|
||||
private void KeyBoxSelected(GUITextBox textBox, Keys key)
|
||||
{
|
||||
textBox.Text = "";
|
||||
CoroutineManager.StartCoroutine(WaitForKeyPress(textBox));
|
||||
}
|
||||
|
||||
private bool MarkUnappliedChanges(GUIButton button, object obj)
|
||||
{
|
||||
UnsavedSettings = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SelectResolution(GUIComponent selected, object userData)
|
||||
{
|
||||
DisplayMode mode = selected.UserData as DisplayMode;
|
||||
if (mode == null) return false;
|
||||
|
||||
if (GraphicsWidth == mode.Width && GraphicsHeight == mode.Height) return false;
|
||||
|
||||
GraphicsWidth = mode.Width;
|
||||
GraphicsHeight = mode.Height;
|
||||
|
||||
|
||||
//GameMain.Graphics.PreferredBackBufferWidth = GraphicsWidth;
|
||||
//GameMain.Graphics.PreferredBackBufferHeight = GraphicsHeight;
|
||||
//GameMain.Graphics.ApplyChanges();
|
||||
|
||||
//CoroutineManager.StartCoroutine(GameMain.Instance.Load());
|
||||
|
||||
UnsavedSettings = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private IEnumerable<object> WaitForKeyPress(GUITextBox keyBox)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
while (keyBox.Selected && PlayerInput.GetKeyboardState.GetPressedKeys().Length==0
|
||||
&& !PlayerInput.LeftButtonClicked() && !PlayerInput.RightButtonClicked())
|
||||
{
|
||||
if (Screen.Selected != GameMain.MainMenuScreen && !GUI.SettingsMenuOpen) yield return CoroutineStatus.Success;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
UnsavedSettings = true;
|
||||
|
||||
int keyIndex = (int)keyBox.UserData;
|
||||
|
||||
if (PlayerInput.LeftButtonClicked())
|
||||
{
|
||||
keyMapping[keyIndex] = new KeyOrMouse(0);
|
||||
keyBox.Text = "Mouse1";
|
||||
}
|
||||
else if (PlayerInput.LeftButtonClicked())
|
||||
{
|
||||
keyMapping[keyIndex] = new KeyOrMouse(1);
|
||||
keyBox.Text = "Mouse2";
|
||||
}
|
||||
else if (PlayerInput.GetKeyboardState.GetPressedKeys().Length > 0)
|
||||
{
|
||||
Keys key = PlayerInput.GetKeyboardState.GetPressedKeys()[0];
|
||||
keyMapping[keyIndex] = new KeyOrMouse(key);
|
||||
keyBox.Text = key.ToString("G");
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
keyBox.Deselect();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private bool ApplyClicked(GUIButton button, object userData)
|
||||
{
|
||||
Save("config.xml");
|
||||
|
||||
settingsFrame.Flash(Color.Green);
|
||||
|
||||
if (GameMain.GraphicsWidth != GameMain.Config.GraphicsWidth || GameMain.GraphicsHeight != GameMain.Config.GraphicsHeight)
|
||||
{
|
||||
new GUIMessageBox("Restart required", "You need to restart the game for the resolution changes to take effect.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Barotrauma
|
||||
None = 0, Any = 1, RightHand = 2, LeftHand = 4, Head = 8, Torso = 16, Legs = 32, Face=64
|
||||
};
|
||||
|
||||
class CharacterInventory : Inventory
|
||||
partial class CharacterInventory : Inventory
|
||||
{
|
||||
private static Texture2D icons;
|
||||
|
||||
@@ -26,81 +26,26 @@ namespace Barotrauma
|
||||
InvSlotType.Head, InvSlotType.Torso, InvSlotType.Legs, InvSlotType.LeftHand, InvSlotType.RightHand, InvSlotType.Face,
|
||||
InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any,
|
||||
InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any, InvSlotType.Any};
|
||||
|
||||
public Vector2[] SlotPositions;
|
||||
|
||||
private GUIButton[] useOnSelfButton;
|
||||
|
||||
|
||||
public CharacterInventory(int capacity, Character character)
|
||||
: base(character, capacity)
|
||||
{
|
||||
this.character = character;
|
||||
|
||||
useOnSelfButton = new GUIButton[2];
|
||||
|
||||
if (icons == null) icons = TextureLoader.FromFile("Content/UI/inventoryIcons.png");
|
||||
|
||||
SlotPositions = new Vector2[limbSlots.Length];
|
||||
|
||||
int rectWidth = 40, rectHeight = 40;
|
||||
int spacing = 10;
|
||||
for (int i = 0; i < SlotPositions.Length; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
//head, torso, legs
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
SlotPositions[i] = new Vector2(
|
||||
spacing,
|
||||
GameMain.GraphicsHeight - (spacing + rectHeight) * (3 - i));
|
||||
break;
|
||||
//lefthand, righthand
|
||||
case 3:
|
||||
case 4:
|
||||
SlotPositions[i] = new Vector2(
|
||||
spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 2),
|
||||
GameMain.GraphicsHeight - (spacing + rectHeight)*3);
|
||||
|
||||
useOnSelfButton[i - 3] = new GUIButton(
|
||||
new Rectangle((int) SlotPositions[i].X, (int) (SlotPositions[i].Y - spacing - rectHeight),
|
||||
rectWidth, rectHeight), "Use", "")
|
||||
{
|
||||
UserData = i,
|
||||
OnClicked = UseItemOnSelf
|
||||
};
|
||||
|
||||
|
||||
break;
|
||||
case 5:
|
||||
SlotPositions[i] = new Vector2(
|
||||
spacing * 2 + rectWidth + (spacing + rectWidth) * (i - 5),
|
||||
GameMain.GraphicsHeight - (spacing + rectHeight) * 3);
|
||||
|
||||
break;
|
||||
default:
|
||||
SlotPositions[i] = new Vector2(
|
||||
spacing * 2 + rectWidth + (spacing + rectWidth) * ((i - 6)%5),
|
||||
GameMain.GraphicsHeight - (spacing + rectHeight) * ((i>10) ? 2 : 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
InitProjSpecific();
|
||||
}
|
||||
|
||||
private bool UseItemOnSelf(GUIButton button, object obj)
|
||||
private bool UseItemOnSelf(int slotIndex)
|
||||
{
|
||||
if (!(obj is int)) return false;
|
||||
|
||||
int slotIndex = (int)obj;
|
||||
|
||||
if (Items[slotIndex] == null) return false;
|
||||
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(Items[slotIndex], new object[] { NetEntityEvent.Type.ApplyStatusEffect });
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
#if CLIENT
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Barotrauma.Particles;
|
||||
#endif
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class Propulsion : ItemComponent
|
||||
{
|
||||
enum UsableIn
|
||||
{
|
||||
Air,Water,Both
|
||||
};
|
||||
|
||||
private float force;
|
||||
|
||||
private string particles;
|
||||
|
||||
private float useState;
|
||||
|
||||
private ParticlePrefab.DrawTargetType usableIn;
|
||||
|
||||
private UsableIn usableIn;
|
||||
|
||||
[HasDefaultValue(0.0f, false)]
|
||||
public float Force
|
||||
@@ -21,13 +28,15 @@ namespace Barotrauma.Items.Components
|
||||
get { return force; }
|
||||
set { force = value; }
|
||||
}
|
||||
|
||||
|
||||
#if CLIENT
|
||||
[HasDefaultValue("", false)]
|
||||
public string Particles
|
||||
{
|
||||
get { return particles; }
|
||||
set { particles = value; }
|
||||
}
|
||||
#endif
|
||||
|
||||
public Propulsion(Item item, XElement element)
|
||||
: base(item,element)
|
||||
@@ -35,14 +44,14 @@ namespace Barotrauma.Items.Components
|
||||
switch (ToolBox.GetAttributeString(element, "usablein", "both").ToLowerInvariant())
|
||||
{
|
||||
case "air":
|
||||
usableIn = ParticlePrefab.DrawTargetType.Air;
|
||||
usableIn = UsableIn.Air;
|
||||
break;
|
||||
case "water":
|
||||
usableIn = ParticlePrefab.DrawTargetType.Water;
|
||||
usableIn = UsableIn.Water;
|
||||
break;
|
||||
case "both":
|
||||
default:
|
||||
usableIn = ParticlePrefab.DrawTargetType.Both;
|
||||
usableIn = UsableIn.Both;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -58,11 +67,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (character.AnimController.InWater)
|
||||
{
|
||||
if (usableIn == ParticlePrefab.DrawTargetType.Air) return true;
|
||||
if (usableIn == UsableIn.Air) return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (usableIn == ParticlePrefab.DrawTargetType.Water) return true;
|
||||
if (usableIn == UsableIn.Water) return true;
|
||||
}
|
||||
|
||||
Vector2 dir = Vector2.Normalize(character.CursorPosition - character.Position);
|
||||
@@ -82,13 +91,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (character.SelectedItems[0] == item) character.AnimController.GetLimb(LimbType.RightHand).body.ApplyForce(propulsion);
|
||||
if (character.SelectedItems[1] == item) character.AnimController.GetLimb(LimbType.LeftHand).body.ApplyForce(propulsion);
|
||||
|
||||
|
||||
#if CLIENT
|
||||
if (!string.IsNullOrWhiteSpace(particles))
|
||||
{
|
||||
GameMain.ParticleManager.CreateParticle(particles, item.WorldPosition,
|
||||
item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi), 0.0f, item.CurrentHull);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
interface IDrawableComponent
|
||||
{
|
||||
#if CLIENT
|
||||
void Draw(SpriteBatch spriteBatch, bool editing);
|
||||
#endif
|
||||
}
|
||||
|
||||
class ItemSound
|
||||
|
||||
@@ -1,87 +1,8 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
class ItemLabel : ItemComponent, IDrawableComponent
|
||||
partial class ItemLabel : ItemComponent, IDrawableComponent
|
||||
{
|
||||
private GUITextBlock textBlock;
|
||||
|
||||
[HasDefaultValue("", true), Editable(100)]
|
||||
public string Text
|
||||
{
|
||||
get { return textBlock.Text.Replace("\n", ""); }
|
||||
set
|
||||
{
|
||||
if (value == TextBlock.Text || item.Rect.Width < 5) return;
|
||||
|
||||
if (textBlock.Rect.Width != item.Rect.Width || textBlock.Rect.Height != item.Rect.Height)
|
||||
{
|
||||
textBlock = null;
|
||||
}
|
||||
|
||||
TextBlock.Text = value;
|
||||
}
|
||||
}
|
||||
|
||||
private Color textColor;
|
||||
[Editable, HasDefaultValue("0.0,0.0,0.0,1.0", true)]
|
||||
public string TextColor
|
||||
{
|
||||
get { return ToolBox.Vector4ToString(textColor.ToVector4()); }
|
||||
set
|
||||
{
|
||||
textColor = new Color(ToolBox.ParseToVector4(value));
|
||||
if (textBlock != null) textBlock.TextColor = textColor;
|
||||
}
|
||||
}
|
||||
|
||||
[Editable, HasDefaultValue(1.0f, true)]
|
||||
public float TextScale
|
||||
{
|
||||
get { return textBlock == null ? 1.0f : textBlock.TextScale; }
|
||||
set
|
||||
{
|
||||
if (textBlock != null) textBlock.TextScale = MathHelper.Clamp(value, 0.1f, 10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
private GUITextBlock TextBlock
|
||||
{
|
||||
get
|
||||
{
|
||||
if (textBlock == null)
|
||||
{
|
||||
textBlock = new GUITextBlock(new Rectangle(item.Rect.X,-item.Rect.Y,item.Rect.Width, item.Rect.Height), "",
|
||||
Color.Transparent, textColor,
|
||||
Alignment.TopLeft, Alignment.Center,
|
||||
null, null, true);
|
||||
textBlock.Font = GUI.SmallFont;
|
||||
textBlock.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
|
||||
textBlock.TextDepth = item.Sprite.Depth - 0.0001f;
|
||||
textBlock.TextScale = TextScale;
|
||||
}
|
||||
return textBlock;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
textBlock.Rect = new Rectangle(item.Rect.X, -item.Rect.Y, item.Rect.Width, item.Rect.Height);
|
||||
}
|
||||
|
||||
public ItemLabel(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
{
|
||||
var drawPos = new Vector2(
|
||||
item.DrawPosition.X - item.Rect.Width/2.0f,
|
||||
-(item.DrawPosition.Y + item.Rect.Height/2.0f));
|
||||
|
||||
textBlock.Draw(spriteBatch, drawPos - textBlock.Rect.Location.ToVector2());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,12 +9,10 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class FixRequirement
|
||||
partial class FixRequirement
|
||||
{
|
||||
string name;
|
||||
|
||||
private static GUIFrame frame;
|
||||
|
||||
List<Skill> requiredSkills;
|
||||
List<string> requiredItems;
|
||||
|
||||
@@ -46,7 +44,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanBeFixed(Character character, GUIComponent reqFrame = null)
|
||||
public bool CanBeFixed(Character character)
|
||||
{
|
||||
if (character == null) return false;
|
||||
|
||||
@@ -57,13 +55,6 @@ namespace Barotrauma
|
||||
bool itemFound = (item != null);
|
||||
|
||||
if (!itemFound) success = false;
|
||||
|
||||
if (reqFrame != null)
|
||||
{
|
||||
GUIComponent component = reqFrame.children.Find(c => c.UserData as string == itemName);
|
||||
GUITextBlock text = component as GUITextBlock;
|
||||
if (text != null) text.TextColor = itemFound ? Color.LightGreen : Color.Red;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Skill skill in requiredSkills)
|
||||
@@ -72,160 +63,9 @@ namespace Barotrauma
|
||||
bool sufficientSkill = characterSkill >= skill.Level;
|
||||
|
||||
if (!sufficientSkill) success = false;
|
||||
|
||||
if (reqFrame != null)
|
||||
{
|
||||
GUIComponent component = reqFrame.children.Find(c => c.UserData as Skill == skill);
|
||||
GUITextBlock text = component as GUITextBlock;
|
||||
if (text != null) text.TextColor = sufficientSkill ? Color.LightGreen : Color.Red;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private static void CreateGUIFrame(Item item)
|
||||
{
|
||||
int width = 400, height = 500;
|
||||
int y = 0;
|
||||
|
||||
frame = new GUIFrame(new Rectangle(0, 0, width, height), null, Alignment.Center, "");
|
||||
frame.Padding = new Vector4(20.0f, 20.0f, 20.0f, 20.0f);
|
||||
frame.UserData = item;
|
||||
|
||||
new GUITextBlock(new Rectangle(0,0,200,20), "Attempting to fix " + item.Name, "", frame);
|
||||
|
||||
y = y + 40;
|
||||
foreach (FixRequirement requirement in item.FixRequirements)
|
||||
{
|
||||
GUIFrame reqFrame = new GUIFrame(
|
||||
new Rectangle(0, y, 0, 20 + Math.Max(requirement.requiredItems.Count, requirement.requiredSkills.Count) * 15),
|
||||
Color.Transparent, null, frame);
|
||||
reqFrame.UserData = requirement;
|
||||
|
||||
|
||||
var fixButton = new GUIButton(new Rectangle(0, 0, 50, 20), "Fix", "", reqFrame);
|
||||
fixButton.OnClicked = FixButtonPressed;
|
||||
fixButton.UserData = requirement;
|
||||
|
||||
var tickBox = new GUITickBox(new Rectangle(70, 0, 20,20), requirement.name, Alignment.Left, reqFrame);
|
||||
tickBox.Enabled = false;
|
||||
|
||||
int y2 = 20;
|
||||
foreach (string itemName in requirement.requiredItems)
|
||||
{
|
||||
var itemBlock = new GUITextBlock(new Rectangle(30, y2, 200, 15), itemName, "", reqFrame);
|
||||
itemBlock.Font = GUI.SmallFont;
|
||||
itemBlock.UserData = itemName;
|
||||
|
||||
y2 += 15;
|
||||
}
|
||||
|
||||
y2 = 20;
|
||||
foreach (Skill skill in requirement.requiredSkills)
|
||||
{
|
||||
var skillBlock = new GUITextBlock(new Rectangle(0, y2, 200, 15), skill.Name + " - " + skill.Level, "", Alignment.Right, Alignment.TopLeft, reqFrame);
|
||||
skillBlock.Font = GUI.SmallFont;
|
||||
skillBlock.UserData = skill;
|
||||
|
||||
|
||||
y2 += 15;
|
||||
}
|
||||
|
||||
y += reqFrame.Rect.Height;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool FixButtonPressed(GUIButton button, object obj)
|
||||
{
|
||||
FixRequirement requirement = obj as FixRequirement;
|
||||
if (requirement == null) return true;
|
||||
|
||||
Item item = frame.UserData as Item;
|
||||
if (item == null) return true;
|
||||
|
||||
if (!requirement.CanBeFixed(Character.Controlled, button.Parent)) return true;
|
||||
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Repair, item.FixRequirements.IndexOf(requirement)});
|
||||
}
|
||||
else if (GameMain.Server != null)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status });
|
||||
requirement.Fixed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
requirement.Fixed = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void UpdateGUIFrame(Item item, Character character)
|
||||
{
|
||||
if (frame == null) return;
|
||||
|
||||
bool unfixedFound = false;
|
||||
foreach (GUIComponent child in frame.children)
|
||||
{
|
||||
FixRequirement requirement = child.UserData as FixRequirement;
|
||||
if (requirement == null) continue;
|
||||
|
||||
if (requirement.Fixed)
|
||||
{
|
||||
child.Color = Color.LightGreen * 0.3f;
|
||||
child.GetChild<GUITickBox>().Selected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool canBeFixed = requirement.CanBeFixed(character, child);
|
||||
unfixedFound = true;
|
||||
//child.GetChild<GUITickBox>().Selected = canBeFixed;
|
||||
GUITickBox tickBox = child.GetChild<GUITickBox>();
|
||||
if (tickBox.Selected)
|
||||
{
|
||||
tickBox.Selected = canBeFixed;
|
||||
requirement.Fixed = canBeFixed;
|
||||
|
||||
}
|
||||
child.Color = Color.Red * 0.2f;
|
||||
//tickBox.State = GUIComponent.ComponentState.None;
|
||||
}
|
||||
}
|
||||
if (!unfixedFound)
|
||||
{
|
||||
item.Condition = 100.0f;
|
||||
frame = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawHud(SpriteBatch spriteBatch, Item item, Character character)
|
||||
{
|
||||
if (frame == null) return;
|
||||
|
||||
frame.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
public static void AddToGUIUpdateList()
|
||||
{
|
||||
if (frame == null) return;
|
||||
|
||||
frame.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public static void UpdateHud(Item item, Character character)
|
||||
{
|
||||
if (frame == null || frame.UserData != item)
|
||||
{
|
||||
CreateGUIFrame(item);
|
||||
}
|
||||
UpdateGUIFrame(item, character);
|
||||
|
||||
if (frame == null) return;
|
||||
|
||||
frame.Update((float)Timing.Step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System.Linq;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -10,65 +8,26 @@ using Barotrauma.Items.Components;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class InventorySlot
|
||||
partial class InventorySlot
|
||||
{
|
||||
public Rectangle Rect;
|
||||
|
||||
public GUIComponent.ComponentState State;
|
||||
|
||||
|
||||
public bool Disabled;
|
||||
|
||||
public bool IsHighlighted
|
||||
{
|
||||
get
|
||||
{
|
||||
return State == GUIComponent.ComponentState.Hover;
|
||||
}
|
||||
}
|
||||
|
||||
public Color Color;
|
||||
|
||||
public Color BorderHighlightColor;
|
||||
private CoroutineHandle BorderHighlightCoroutine;
|
||||
|
||||
public InventorySlot(Rectangle rect)
|
||||
{
|
||||
Rect = rect;
|
||||
|
||||
#if CLIENT
|
||||
State = GUIComponent.ComponentState.None;
|
||||
|
||||
Color = Color.White * 0.4f;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ShowBorderHighlight(Color color, float fadeInDuration, float fadeOutDuration)
|
||||
{
|
||||
if (BorderHighlightCoroutine != null)
|
||||
{
|
||||
BorderHighlightCoroutine = null;
|
||||
}
|
||||
|
||||
BorderHighlightCoroutine = CoroutineManager.StartCoroutine(UpdateBorderHighlight(color, fadeInDuration, fadeOutDuration));
|
||||
}
|
||||
|
||||
private IEnumerable<object> UpdateBorderHighlight(Color color, float fadeInDuration, float fadeOutDuration)
|
||||
{
|
||||
float t = 0.0f;
|
||||
while (t < fadeInDuration + fadeOutDuration)
|
||||
{
|
||||
BorderHighlightColor = (t < fadeInDuration) ?
|
||||
Color.Lerp(Color.Transparent, color, t / fadeInDuration) :
|
||||
Color.Lerp(color, Color.Transparent, (t - fadeInDuration) / fadeOutDuration);
|
||||
|
||||
t += CoroutineManager.DeltaTime;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
}
|
||||
|
||||
class Inventory : IServerSerializable, IClientSerializable
|
||||
partial class Inventory : IServerSerializable, IClientSerializable
|
||||
{
|
||||
public static InventorySlot draggingSlot;
|
||||
public static Item draggingItem;
|
||||
@@ -86,8 +45,6 @@ namespace Barotrauma
|
||||
|
||||
protected int capacity;
|
||||
|
||||
private Vector2 centerPos;
|
||||
|
||||
protected int selectedSlot = -1;
|
||||
|
||||
protected InventorySlot[] slots;
|
||||
@@ -101,14 +58,18 @@ namespace Barotrauma
|
||||
private float syncItemsDelay;
|
||||
private CoroutineHandle syncItemsCoroutine;
|
||||
|
||||
private Vector2 centerPos;
|
||||
|
||||
public Vector2 CenterPos
|
||||
{
|
||||
get { return centerPos; }
|
||||
set
|
||||
{
|
||||
centerPos = value;
|
||||
#if CLIENT
|
||||
centerPos.X *= GameMain.GraphicsWidth;
|
||||
centerPos.Y *= GameMain.GraphicsHeight;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +156,9 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
#if CLIENT
|
||||
if (slots != null && createNetworkEvent) slots[i].ShowBorderHighlight(Color.Red, 0.1f, 0.9f);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -213,7 +176,9 @@ namespace Barotrauma
|
||||
Items[i] = item;
|
||||
item.ParentInventory = this;
|
||||
|
||||
#if CLIENT
|
||||
if (slots != null) slots[i].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
|
||||
#endif
|
||||
|
||||
if (item.body != null)
|
||||
{
|
||||
@@ -232,10 +197,12 @@ namespace Barotrauma
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(Owner as IServerSerializable, new object[] { NetEntityEvent.Type.InventoryState });
|
||||
}
|
||||
#if CLIENT
|
||||
else if (GameMain.Client != null)
|
||||
{
|
||||
GameMain.Client.CreateEntityEvent(Owner as IClientSerializable, new object[] { NetEntityEvent.Type.InventoryState });
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public Item FindItem(string itemName)
|
||||
@@ -311,79 +278,13 @@ namespace Barotrauma
|
||||
|
||||
}
|
||||
|
||||
public virtual void Draw(SpriteBatch spriteBatch, bool subInventory = false)
|
||||
{
|
||||
if (slots == null || isSubInventory != subInventory) return;
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (slots[i].Disabled) continue;
|
||||
|
||||
//don't draw the item if it's being dragged out of the slot
|
||||
bool drawItem = draggingItem == null || draggingItem != Items[i] || slots[i].IsHighlighted;
|
||||
|
||||
DrawSlot(spriteBatch, slots[i], Items[i], drawItem);
|
||||
}
|
||||
|
||||
if (draggingItem != null &&
|
||||
(draggingSlot == null || (!draggingSlot.Rect.Contains(PlayerInput.MousePosition) && draggingItem.ParentInventory == this)))
|
||||
{
|
||||
Rectangle dragRect = new Rectangle(
|
||||
(int)PlayerInput.MousePosition.X - 10,
|
||||
(int)PlayerInput.MousePosition.Y - 10,
|
||||
40, 40);
|
||||
|
||||
DrawSlot(spriteBatch, new InventorySlot(dragRect), draggingItem);
|
||||
}
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (slots[i].IsHighlighted && !slots[i].Disabled && Items[i] != null)
|
||||
{
|
||||
string toolTip = "";
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
toolTip = Items[i].ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
toolTip = string.IsNullOrEmpty(Items[i].Description) ?
|
||||
Items[i].Name :
|
||||
Items[i].Name + '\n' + Items[i].Description;
|
||||
}
|
||||
|
||||
DrawToolTip(spriteBatch, toolTip, slots[i].Rect);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawToolTip(SpriteBatch spriteBatch, string toolTip, Rectangle highlightedSlot)
|
||||
{
|
||||
int maxWidth = 300;
|
||||
|
||||
toolTip = ToolBox.WrapText(toolTip, maxWidth, GUI.Font);
|
||||
|
||||
Vector2 textSize = GUI.Font.MeasureString(toolTip);
|
||||
Vector2 rectSize = textSize * 1.2f;
|
||||
|
||||
Vector2 pos = new Vector2(highlightedSlot.Right, highlightedSlot.Y-rectSize.Y);
|
||||
pos.X = (int)(pos.X + 3);
|
||||
pos.Y = (int)pos.Y;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, pos, rectSize, Color.Black * 0.8f, true);
|
||||
GUI.Font.DrawString(spriteBatch, toolTip,
|
||||
new Vector2((int)(pos.X + rectSize.X * 0.5f), (int)(pos.Y + rectSize.Y * 0.5f)),
|
||||
Color.White, 0.0f,
|
||||
new Vector2((int)(textSize.X * 0.5f), (int)(textSize.Y * 0.5f)),
|
||||
1.0f, SpriteEffects.None, 0.0f);
|
||||
}
|
||||
|
||||
protected void UpdateSlot(InventorySlot slot, int slotIndex, Item item, bool isSubSlot)
|
||||
{
|
||||
bool mouseOn = slot.Rect.Contains(PlayerInput.MousePosition) && !Locked;
|
||||
|
||||
#if CLIENT
|
||||
slot.State = GUIComponent.ComponentState.None;
|
||||
#endif
|
||||
|
||||
if (!(this is CharacterInventory) && !mouseOn && selectedSlot==slotIndex)
|
||||
{
|
||||
@@ -393,7 +294,9 @@ namespace Barotrauma
|
||||
if (mouseOn &&
|
||||
(draggingItem!=null || selectedSlot==slotIndex || selectedSlot==-1))
|
||||
{
|
||||
#if CLIENT
|
||||
slot.State = GUIComponent.ComponentState.Hover;
|
||||
#endif
|
||||
|
||||
if (!isSubSlot && selectedSlot == -1)
|
||||
{
|
||||
@@ -420,11 +323,15 @@ namespace Barotrauma
|
||||
//selectedSlot = slotIndex;
|
||||
if (TryPutItem(draggingItem, slotIndex, true))
|
||||
{
|
||||
#if CLIENT
|
||||
if (slots != null) slots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if CLIENT
|
||||
if (slots != null) slots[slotIndex].ShowBorderHighlight(Color.Red, 0.1f, 0.9f);
|
||||
#endif
|
||||
}
|
||||
draggingItem = null;
|
||||
draggingSlot = null;
|
||||
@@ -460,83 +367,11 @@ namespace Barotrauma
|
||||
|
||||
container.Inventory.isSubInventory = true;
|
||||
|
||||
#if CLIENT
|
||||
slots[slotIndex].State = GUIComponent.ComponentState.Hover;
|
||||
|
||||
container.Inventory.Update(deltaTime, true);
|
||||
}
|
||||
|
||||
public void DrawSubInventory(SpriteBatch spriteBatch, int slotIndex)
|
||||
{
|
||||
var item = Items[slotIndex];
|
||||
if (item == null) return;
|
||||
|
||||
var container = item.GetComponent<ItemContainer>();
|
||||
if (container == null) return;
|
||||
|
||||
if (container.Inventory.slots == null || !container.Inventory.isSubInventory) return;
|
||||
|
||||
int itemCapacity = container.Capacity;
|
||||
|
||||
#if DEBUG
|
||||
System.Diagnostics.Debug.Assert(slotIndex >= 0 && slotIndex < Items.Length);
|
||||
#else
|
||||
if (slotIndex < 0 || slotIndex >= Items.Length) return;
|
||||
#endif
|
||||
|
||||
var slot = slots[slotIndex];
|
||||
Rectangle containerRect = new Rectangle(slot.Rect.X - 5, slot.Rect.Y - (40 + 10) * itemCapacity - 5,
|
||||
slot.Rect.Width + 10, slot.Rect.Height + (40 + 10) * itemCapacity + 10);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(containerRect.X, containerRect.Y, containerRect.Width, containerRect.Height - slot.Rect.Height - 5), Color.Black * 0.8f, true);
|
||||
GUI.DrawRectangle(spriteBatch, containerRect, Color.White);
|
||||
|
||||
container.Inventory.Draw(spriteBatch, true);
|
||||
|
||||
if (!containerRect.Contains(PlayerInput.MousePosition))
|
||||
{
|
||||
if (draggingItem == null || draggingItem.Container != item) selectedSlot = -1;
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawSlot(SpriteBatch spriteBatch, InventorySlot slot, Item item, bool drawItem=true)
|
||||
{
|
||||
Rectangle rect = slot.Rect;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, rect, (slot.IsHighlighted ? Color.Red * 0.4f : slot.Color), true);
|
||||
|
||||
if (item != null && drawItem)
|
||||
{
|
||||
if (item.Condition < 100.0f)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Bottom - 8, rect.Width, 8), Color.Black*0.8f, true);
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Rectangle(rect.X, rect.Bottom - 8, (int)(rect.Width * item.Condition / 100.0f), 8),
|
||||
Color.Lerp(Color.Red, Color.Green, item.Condition / 100.0f)*0.8f, true);
|
||||
}
|
||||
|
||||
var containedItems = item.ContainedItems;
|
||||
if (containedItems != null && containedItems.Length == 1 && containedItems[0].Condition < 100.0f)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, rect.Y, rect.Width, 8), Color.Black*0.8f, true);
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Rectangle(rect.X, rect.Y, (int)(rect.Width * containedItems[0].Condition / 100.0f), 8),
|
||||
Color.Lerp(Color.Red, Color.Green, containedItems[0].Condition / 100.0f)*0.8f, true);
|
||||
}
|
||||
}
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, rect, (slot.IsHighlighted ? Color.Red * 0.4f : slot.Color), false);
|
||||
|
||||
if (slot.BorderHighlightColor != Color.Transparent)
|
||||
{
|
||||
Rectangle highlightRect = slot.Rect;
|
||||
highlightRect.Inflate(3,3);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, highlightRect, slot.BorderHighlightColor, false, 0, 5);
|
||||
}
|
||||
|
||||
if (item == null || !drawItem) return;
|
||||
|
||||
item.Sprite.Draw(spriteBatch, new Vector2(rect.X + rect.Width / 2, rect.Y + rect.Height / 2), item.Color);
|
||||
container.Inventory.Update(deltaTime, true);
|
||||
}
|
||||
|
||||
public void ClientWrite(NetBuffer msg, object[] extraData = null)
|
||||
|
||||
@@ -34,6 +34,15 @@ namespace Barotrauma
|
||||
|
||||
//the position and dimensions of the entity
|
||||
protected Rectangle rect;
|
||||
|
||||
//is the mouse inside the rect
|
||||
protected bool isHighlighted;
|
||||
|
||||
public bool IsHighlighted
|
||||
{
|
||||
get { return isHighlighted; }
|
||||
set { isHighlighted = value; }
|
||||
}
|
||||
|
||||
private static bool resizing;
|
||||
private int resizeDirX, resizeDirY;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
class Structure : MapEntity, IDamageable, IServerSerializable
|
||||
partial class Structure : MapEntity, IDamageable, IServerSerializable
|
||||
{
|
||||
public static int wallSectionSize = 96;
|
||||
public static List<Structure> WallList = new List<Structure>();
|
||||
@@ -517,91 +517,6 @@ namespace Barotrauma
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
|
||||
{
|
||||
if (prefab.sprite == null) return;
|
||||
|
||||
Draw(spriteBatch, editing, back, null);
|
||||
}
|
||||
|
||||
public override void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect)
|
||||
{
|
||||
Draw(spriteBatch, false, false, damageEffect);
|
||||
}
|
||||
|
||||
|
||||
private void Draw(SpriteBatch spriteBatch, bool editing, bool back = true, Effect damageEffect = null)
|
||||
{
|
||||
if (prefab.sprite == null) return;
|
||||
|
||||
Color color = (isHighlighted) ? Color.Orange : Color.White;
|
||||
if (IsSelected && editing)
|
||||
{
|
||||
color = Color.Red;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(rect.X, -rect.Y, rect.Width, rect.Height), color);
|
||||
}
|
||||
|
||||
Vector2 drawOffset = Submarine == null ? Vector2.Zero : Submarine.DrawPosition;
|
||||
|
||||
float depth = prefab.sprite.Depth;
|
||||
depth -= (ID % 255) * 0.000001f;
|
||||
|
||||
if (back && damageEffect == null)
|
||||
{
|
||||
if (prefab.BackgroundSprite != null)
|
||||
{
|
||||
prefab.BackgroundSprite.DrawTiled(
|
||||
spriteBatch,
|
||||
new Vector2(rect.X + drawOffset.X, -(rect.Y + drawOffset.Y)),
|
||||
new Vector2(rect.Width, rect.Height),
|
||||
color, Point.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
SpriteEffects oldEffects = prefab.sprite.effects;
|
||||
prefab.sprite.effects ^= SpriteEffects;
|
||||
|
||||
if (back == prefab.sprite.Depth > 0.5f || editing)
|
||||
{
|
||||
for (int i = 0; i < sections.Length; i++)
|
||||
{
|
||||
if (damageEffect != null)
|
||||
{
|
||||
float newCutoff = Math.Min((sections[i].damage / prefab.MaxHealth), 0.65f);
|
||||
|
||||
if (Math.Abs(newCutoff - Submarine.DamageEffectCutoff) > 0.01f)
|
||||
{
|
||||
damageEffect.Parameters["aCutoff"].SetValue(newCutoff);
|
||||
damageEffect.Parameters["cCutoff"].SetValue(newCutoff * 1.2f);
|
||||
|
||||
damageEffect.CurrentTechnique.Passes[0].Apply();
|
||||
|
||||
Submarine.DamageEffectCutoff = newCutoff;
|
||||
}
|
||||
}
|
||||
|
||||
Point textureOffset = new Point(
|
||||
Math.Abs(rect.Location.X - sections[i].rect.Location.X),
|
||||
Math.Abs(rect.Location.Y - sections[i].rect.Location.Y));
|
||||
|
||||
if (flippedX && isHorizontal)
|
||||
{
|
||||
textureOffset.X = rect.Width - textureOffset.X - sections[i].rect.Width;
|
||||
}
|
||||
|
||||
prefab.sprite.DrawTiled(
|
||||
spriteBatch,
|
||||
new Vector2(sections[i].rect.X + drawOffset.X, -(sections[i].rect.Y + drawOffset.Y)),
|
||||
new Vector2(sections[i].rect.Width, sections[i].rect.Height),
|
||||
color,
|
||||
textureOffset, depth);
|
||||
}
|
||||
}
|
||||
|
||||
prefab.sprite.effects = oldEffects;
|
||||
}
|
||||
|
||||
private bool OnWallCollision(Fixture f1, Fixture f2, Contact contact)
|
||||
{
|
||||
if (prefab.IsPlatform)
|
||||
@@ -632,10 +547,12 @@ namespace Barotrauma
|
||||
|
||||
if (impact < 10.0f) return true;
|
||||
|
||||
#if CLIENT
|
||||
SoundPlayer.PlayDamageSound(DamageSoundType.StructureBlunt, impact,
|
||||
new Vector2(
|
||||
sections[section].rect.X + sections[section].rect.Width / 2,
|
||||
sections[section].rect.Y - sections[section].rect.Height / 2));
|
||||
#endif
|
||||
|
||||
AddDamage(section, impact);
|
||||
}
|
||||
@@ -685,6 +602,7 @@ namespace Barotrauma
|
||||
|
||||
var section = sections[sectionIndex];
|
||||
|
||||
#if CLIENT
|
||||
float particleAmount = Math.Min(Health - section.damage, damage) * Rand.Range(0.01f, 1.0f);
|
||||
|
||||
particleAmount = Math.Min(particleAmount + Rand.Range(-5,1), 100);
|
||||
@@ -695,10 +613,11 @@ namespace Barotrauma
|
||||
Rand.Range(section.rect.Y - section.rect.Height, section.rect.Y));
|
||||
|
||||
if (Submarine != null) particlePos += Submarine.DrawPosition;
|
||||
|
||||
|
||||
var particle = GameMain.ParticleManager.CreateParticle("shrapnel", particlePos, Rand.Vector(Rand.Range(1.0f, 50.0f)));
|
||||
if (particle == null) break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GameMain.Client == null) SetDamage(sectionIndex, section.damage + damage);
|
||||
}
|
||||
@@ -753,18 +672,20 @@ namespace Barotrauma
|
||||
int i = FindSectionIndex(transformedPos);
|
||||
if (i == -1) return new AttackResult(0.0f, 0.0f);
|
||||
|
||||
GameMain.ParticleManager.CreateParticle("dustcloud", SectionPosition(i), 0.0f, 0.0f);
|
||||
|
||||
float damageAmount = attack.GetStructureDamage(deltaTime);
|
||||
|
||||
AddDamage(i, damageAmount);
|
||||
|
||||
#if CLIENT
|
||||
GameMain.ParticleManager.CreateParticle("dustcloud", SectionPosition(i), 0.0f, 0.0f);
|
||||
|
||||
if (playSound && !SectionBodyDisabled(i))
|
||||
{
|
||||
DamageSoundType damageSoundType = (attack.DamageType == DamageType.Blunt) ? DamageSoundType.StructureBlunt : DamageSoundType.StructureSlash;
|
||||
SoundPlayer.PlayDamageSound(damageSoundType, damageAmount, worldPosition);
|
||||
}
|
||||
|
||||
AddDamage(i, damageAmount);
|
||||
|
||||
#endif
|
||||
|
||||
return new AttackResult(damageAmount, 0.0f);
|
||||
}
|
||||
|
||||
@@ -928,39 +849,6 @@ namespace Barotrauma
|
||||
CreateSections();
|
||||
}
|
||||
|
||||
public override XElement Save(XElement parentElement)
|
||||
{
|
||||
XElement element = new XElement("Structure");
|
||||
|
||||
element.Add(new XAttribute("name", prefab.Name),
|
||||
new XAttribute("ID", ID),
|
||||
new XAttribute("rect",
|
||||
(int)(rect.X - Submarine.HiddenSubPosition.X) + "," +
|
||||
(int)(rect.Y - Submarine.HiddenSubPosition.Y) + "," +
|
||||
rect.Width + "," + rect.Height));
|
||||
|
||||
for (int i = 0; i < sections.Length; i++)
|
||||
{
|
||||
if (sections[i].damage == 0.0f) continue;
|
||||
|
||||
var sectionElement =
|
||||
new XElement("section",
|
||||
new XAttribute("i", i),
|
||||
new XAttribute("damage", sections[i].damage));
|
||||
|
||||
if (sections[i].gap!=null)
|
||||
{
|
||||
sectionElement.Add(new XAttribute("gap", sections[i].gap.ID));
|
||||
}
|
||||
|
||||
element.Add(sectionElement);
|
||||
}
|
||||
|
||||
parentElement.Add(element);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
public static void Load(XElement element, Submarine submarine)
|
||||
{
|
||||
string rectString = ToolBox.GetAttributeString(element, "rect", "0,0,0,0");
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class StructurePrefab : MapEntityPrefab
|
||||
partial class StructurePrefab : MapEntityPrefab
|
||||
{
|
||||
//public static List<StructurePrefab> list = new List<StructurePrefab>();
|
||||
|
||||
@@ -188,38 +188,5 @@ namespace Barotrauma
|
||||
|
||||
if (PlayerInput.RightButtonHeld()) selected = null;
|
||||
}
|
||||
|
||||
public override void DrawPlacing(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
Vector2 position = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
|
||||
//Vector2 placeSize = size;
|
||||
|
||||
Rectangle newRect = new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y);
|
||||
|
||||
|
||||
if (placePosition == Vector2.Zero)
|
||||
{
|
||||
if (PlayerInput.LeftButtonHeld())
|
||||
placePosition = Submarine.MouseToWorldGrid(cam, Submarine.MainSub);
|
||||
|
||||
newRect.X = (int)position.X;
|
||||
newRect.Y = (int)position.Y;
|
||||
|
||||
//sprite.Draw(spriteBatch, new Vector2(position.X, -position.Y), placeSize, Color.White);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 placeSize = size;
|
||||
if (resizeHorizontal) placeSize.X = position.X - placePosition.X;
|
||||
if (resizeVertical) placeSize.Y = placePosition.Y - position.Y;
|
||||
|
||||
newRect = Submarine.AbsRect(placePosition, placeSize);
|
||||
}
|
||||
|
||||
sprite.DrawTiled(spriteBatch, new Vector2(newRect.X, -newRect.Y), new Vector2(newRect.Width, newRect.Height), Color.White);
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X - GameMain.GraphicsWidth, -newRect.Y, newRect.Width + GameMain.GraphicsWidth * 2, newRect.Height), Color.White);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(newRect.X, -newRect.Y - GameMain.GraphicsHeight, newRect.Width, newRect.Height + GameMain.GraphicsHeight * 2), Color.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
//using Microsoft.Xna.Framework.Graphics;
|
||||
//using Microsoft.Xna.Framework.Input;
|
||||
using System.Collections.ObjectModel;
|
||||
using Barotrauma.Items.Components;
|
||||
using FarseerPhysics.Dynamics;
|
||||
@@ -13,16 +13,12 @@ using FarseerPhysics.Dynamics;
|
||||
namespace Barotrauma
|
||||
{
|
||||
public enum SpawnType { Path, Human, Enemy, Cargo };
|
||||
class WayPoint : MapEntity
|
||||
partial class WayPoint : MapEntity
|
||||
{
|
||||
public static List<WayPoint> WayPointList = new List<WayPoint>();
|
||||
|
||||
public static bool ShowWayPoints = true, ShowSpawnPoints = true;
|
||||
|
||||
private static Texture2D iconTexture;
|
||||
private const int IconSize = 32;
|
||||
private static int[] iconIndices = { 3, 0, 1, 2 };
|
||||
|
||||
protected SpawnType spawnType;
|
||||
|
||||
//characters spawning at the waypoint will be given an ID card with these tags
|
||||
@@ -102,10 +98,12 @@ namespace Barotrauma
|
||||
linkedTo = new ObservableCollection<MapEntity>();
|
||||
idCardTags = new string[0];
|
||||
|
||||
#if CLIENT
|
||||
if (iconTexture==null)
|
||||
{
|
||||
iconTexture = Sprite.LoadTexture("Content/Map/waypointIcons.png");
|
||||
}
|
||||
#endif
|
||||
|
||||
InsertToList();
|
||||
WayPointList.Add(this);
|
||||
@@ -125,203 +123,13 @@ namespace Barotrauma
|
||||
|
||||
public override bool IsMouseOn(Vector2 position)
|
||||
{
|
||||
#if CLIENT
|
||||
if (IsHidden()) return false;
|
||||
#endif
|
||||
|
||||
return base.IsMouseOn(position);
|
||||
}
|
||||
|
||||
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back=true)
|
||||
{
|
||||
if (!editing && !GameMain.DebugDraw) return;
|
||||
|
||||
if (IsHidden()) return;
|
||||
|
||||
//Rectangle drawRect =
|
||||
// Submarine == null ? rect : new Rectangle((int)(Submarine.DrawPosition.X + rect.X), (int)(Submarine.DrawPosition.Y + rect.Y), rect.Width, rect.Height);
|
||||
|
||||
Vector2 drawPos = Position;
|
||||
if (Submarine!=null) drawPos += Submarine.DrawPosition;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
|
||||
Color clr = currentHull == null ? Color.Blue : Color.White;
|
||||
if (IsSelected) clr = Color.Red;
|
||||
if (isHighlighted) clr = Color.DarkRed;
|
||||
|
||||
int iconX = iconIndices[(int)spawnType]*IconSize % iconTexture.Width;
|
||||
int iconY = (int)(Math.Floor(iconIndices[(int)spawnType]*IconSize / (float)iconTexture.Width))*IconSize;
|
||||
|
||||
int iconSize = ConnectedGap == null && Ladders == null ? IconSize : (int)(IconSize * 1.5f);
|
||||
|
||||
spriteBatch.Draw(iconTexture,
|
||||
new Rectangle((int)(drawPos.X - iconSize/2), (int)(drawPos.Y - iconSize/2), iconSize, iconSize),
|
||||
new Rectangle(iconX, iconY, IconSize,IconSize), clr);
|
||||
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle(drawRect.X, -drawRect.Y, rect.Width, rect.Height), clr, true);
|
||||
|
||||
//GUI.SmallFont.DrawString(spriteBatch, Position.ToString(), new Vector2(Position.X, -Position.Y), Color.White);
|
||||
|
||||
foreach (MapEntity e in linkedTo)
|
||||
{
|
||||
GUI.DrawLine(spriteBatch,
|
||||
drawPos,
|
||||
new Vector2(e.DrawPosition.X, -e.DrawPosition.Y),
|
||||
Color.Green);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsHidden()
|
||||
{
|
||||
if (spawnType == SpawnType.Path)
|
||||
{
|
||||
return (!GameMain.DebugDraw && !ShowWayPoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (!GameMain.DebugDraw && !ShowSpawnPoints);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateEditing(Camera cam)
|
||||
{
|
||||
if (editingHUD == null || editingHUD.UserData != this)
|
||||
{
|
||||
editingHUD = CreateEditingHUD();
|
||||
}
|
||||
|
||||
editingHUD.Update((float)Timing.Step);
|
||||
|
||||
if (PlayerInput.LeftButtonClicked())
|
||||
{
|
||||
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
|
||||
foreach (MapEntity e in mapEntityList)
|
||||
{
|
||||
if (e.GetType() != typeof(WayPoint)) continue;
|
||||
if (e == this) continue;
|
||||
|
||||
if (!Submarine.RectContains(e.Rect, position)) continue;
|
||||
|
||||
linkedTo.Add(e);
|
||||
e.linkedTo.Add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawEditing(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
if (editingHUD != null) editingHUD.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
private bool ChangeSpawnType(GUIButton button, object obj)
|
||||
{
|
||||
GUITextBlock spawnTypeText = button.Parent as GUITextBlock;
|
||||
|
||||
spawnType += (int)button.UserData;
|
||||
|
||||
if (spawnType > SpawnType.Cargo) spawnType = SpawnType.Human;
|
||||
if (spawnType < SpawnType.Human) spawnType = SpawnType.Cargo;
|
||||
|
||||
spawnTypeText.Text = spawnType.ToString();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool EnterIDCardTags(GUITextBox textBox, string text)
|
||||
{
|
||||
IdCardTags = text.Split(',');
|
||||
textBox.Text = text;
|
||||
textBox.Color = Color.Green;
|
||||
|
||||
textBox.Deselect();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool EnterAssignedJob(GUITextBox textBox, string text)
|
||||
{
|
||||
string trimmedName = text.ToLowerInvariant().Trim();
|
||||
assignedJob = JobPrefab.List.Find(jp => jp.Name.ToLowerInvariant() == trimmedName);
|
||||
|
||||
if (assignedJob !=null && trimmedName!="none")
|
||||
{
|
||||
textBox.Color = Color.Green;
|
||||
textBox.Text = (assignedJob == null) ? "None" : assignedJob.Name;
|
||||
}
|
||||
|
||||
textBox.Deselect();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TextBoxChanged(GUITextBox textBox, string text)
|
||||
{
|
||||
textBox.Color = Color.Red;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private GUIComponent CreateEditingHUD(bool inGame = false)
|
||||
{
|
||||
int width = 500;
|
||||
int height = spawnType == SpawnType.Path ? 100 : 140;
|
||||
int x = GameMain.GraphicsWidth / 2 - width / 2, y = 10;
|
||||
|
||||
editingHUD = new GUIFrame(new Rectangle(x, y, width, height), Color.Black * 0.5f);
|
||||
editingHUD.Padding = new Vector4(10, 10, 0, 0);
|
||||
editingHUD.UserData = this;
|
||||
|
||||
if (spawnType == SpawnType.Path)
|
||||
{
|
||||
new GUITextBlock(new Rectangle(0, 0, 100, 20), "Editing waypoint", "", editingHUD);
|
||||
new GUITextBlock(new Rectangle(0, 20, 100, 20), "Hold space to link to another waypoint", "", editingHUD);
|
||||
}
|
||||
else
|
||||
{
|
||||
new GUITextBlock(new Rectangle(0, 0, 100, 20), "Editing spawnpoint", "", editingHUD);
|
||||
new GUITextBlock(new Rectangle(0, 25, 100, 20), "Spawn type: ", "", editingHUD);
|
||||
|
||||
var spawnTypeText = new GUITextBlock(new Rectangle(0, 25, 200, 20), spawnType.ToString(), "", Alignment.Right, Alignment.TopLeft, editingHUD);
|
||||
|
||||
var button = new GUIButton(new Rectangle(-30,0,20,20), "-", Alignment.Right, "", spawnTypeText);
|
||||
button.UserData = -1;
|
||||
button.OnClicked = ChangeSpawnType;
|
||||
|
||||
button = new GUIButton(new Rectangle(0, 0, 20, 20), "+", Alignment.Right, "", spawnTypeText);
|
||||
button.UserData = 1;
|
||||
button.OnClicked = ChangeSpawnType;
|
||||
|
||||
y = 40 + 20;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, y, 100, 20), "ID Card tags:", Color.Transparent, Color.White, Alignment.TopLeft, null, editingHUD);
|
||||
GUITextBox propertyBox = new GUITextBox(new Rectangle(100, y, 200, 20), "", editingHUD);
|
||||
propertyBox.Text = string.Join(", ", idCardTags);
|
||||
propertyBox.OnEnterPressed = EnterIDCardTags;
|
||||
propertyBox.OnTextChanged = TextBoxChanged;
|
||||
propertyBox.ToolTip = "Characters spawning at this spawnpoint will have the specified tags added to their ID card. You can, for example, use these tags to limit access to some parts of the sub.";
|
||||
|
||||
y = y + 30;
|
||||
|
||||
new GUITextBlock(new Rectangle(0, y, 100, 20), "Assigned job:", Color.Transparent, Color.White, Alignment.TopLeft, null, editingHUD);
|
||||
propertyBox = new GUITextBox(new Rectangle(100, y, 200, 20), "", editingHUD);
|
||||
propertyBox.Text = (assignedJob == null) ? "None" : assignedJob.Name;
|
||||
propertyBox.OnEnterPressed = EnterAssignedJob;
|
||||
propertyBox.OnTextChanged = TextBoxChanged;
|
||||
propertyBox.ToolTip = "Only characters with the specified job will spawn at this spawnpoint.";
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//GUI.Font.DrawString(spriteBatch, "Spawnpoint: " + spawnType.ToString() + " +/-", new Vector2(x, y + 40), Color.Black);
|
||||
|
||||
|
||||
y = y + 30;
|
||||
|
||||
return editingHUD;
|
||||
}
|
||||
|
||||
public static void GenerateSubWaypoints(Submarine submarine)
|
||||
{
|
||||
if (!Hull.hullList.Any())
|
||||
@@ -747,42 +555,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public override XElement Save(XElement parentElement)
|
||||
{
|
||||
if (MoveWithLevel) return null;
|
||||
XElement element = new XElement("WayPoint");
|
||||
|
||||
element.Add(new XAttribute("ID", ID),
|
||||
new XAttribute("x", (int)(rect.X - Submarine.HiddenSubPosition.X)),
|
||||
new XAttribute("y", (int)(rect.Y - Submarine.HiddenSubPosition.Y)),
|
||||
new XAttribute("spawn", spawnType));
|
||||
|
||||
if (idCardTags.Length > 0)
|
||||
{
|
||||
element.Add(new XAttribute("idcardtags", string.Join(",", idCardTags)));
|
||||
}
|
||||
|
||||
if (assignedJob != null) element.Add(new XAttribute("job", assignedJob.Name));
|
||||
|
||||
|
||||
if (ConnectedGap != null) element.Add(new XAttribute("gap", ConnectedGap.ID));
|
||||
if (Ladders != null) element.Add(new XAttribute("ladders", Ladders.Item.ID));
|
||||
|
||||
parentElement.Add(element);
|
||||
|
||||
if (linkedTo != null)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (MapEntity e in linkedTo)
|
||||
{
|
||||
element.Add(new XAttribute("linkedto" + i, e.ID));
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
public static void Load(XElement element, Submarine submarine)
|
||||
{
|
||||
Rectangle rect = new Rectangle(
|
||||
|
||||
@@ -39,13 +39,10 @@ namespace Barotrauma.Networking
|
||||
private IRestResponse masterServerResponse;
|
||||
|
||||
private ServerLog log;
|
||||
private GUIButton showLogButton;
|
||||
|
||||
private bool initiatedStartGame;
|
||||
private CoroutineHandle startGameCoroutine;
|
||||
|
||||
private GUIScrollBar clientListScrollBar;
|
||||
|
||||
public TraitorManager TraitorManager;
|
||||
|
||||
private ServerEntityEventManager entityEventManager;
|
||||
@@ -122,40 +119,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
var endRoundButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170, 20, 150, 20), "End round", Alignment.TopLeft, "", inGameHUD);
|
||||
endRoundButton.OnClicked = (btn, userdata) => { EndGame(); return true; };
|
||||
|
||||
log = new ServerLog(name);
|
||||
showLogButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170, 20, 150, 20), "Server Log", Alignment.TopLeft, "", inGameHUD);
|
||||
showLogButton.OnClicked = (GUIButton button, object userData) =>
|
||||
{
|
||||
if (log.LogFrame == null)
|
||||
{
|
||||
log.CreateLogFrame();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.LogFrame = null;
|
||||
GUIComponent.KeyboardDispatcher.Subscriber = null;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
GUIButton settingsButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 170 - 170 - 170, 20, 150, 20), "Settings", Alignment.TopLeft, "", inGameHUD);
|
||||
settingsButton.OnClicked = ToggleSettingsFrame;
|
||||
settingsButton.UserData = "settingsButton";
|
||||
|
||||
entityEventManager = new ServerEntityEventManager(this);
|
||||
|
||||
whitelist = new WhiteList();
|
||||
banList = new BanList();
|
||||
|
||||
LoadSettings();
|
||||
LoadClientPermissions();
|
||||
|
||||
//----------------------------------------
|
||||
InitProjSpecific();
|
||||
|
||||
CoroutineManager.StartCoroutine(StartServer(isPublic));
|
||||
}
|
||||
@@ -181,6 +145,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
System.Net.Sockets.SocketException socketException = e as System.Net.Sockets.SocketException;
|
||||
|
||||
#if CLIENT
|
||||
if (socketException != null && socketException.SocketErrorCode == System.Net.Sockets.SocketError.AddressAlreadyInUse)
|
||||
{
|
||||
new GUIMessageBox("Starting the server failed", e.Message + ". Are you trying to run multiple servers on the same port?");
|
||||
@@ -189,6 +154,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
new GUIMessageBox("Starting the server failed", e.Message);
|
||||
}
|
||||
#endif
|
||||
|
||||
error = true;
|
||||
}
|
||||
@@ -197,26 +163,27 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (server != null) server.Shutdown("Error while starting the server");
|
||||
|
||||
#if CLIENT
|
||||
GameMain.NetworkMember = null;
|
||||
#elif SERVER
|
||||
Environment.Exit(-1);
|
||||
#endif
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
if (config.EnableUPnP)
|
||||
{
|
||||
server.UPnP.ForwardPort(config.Port, "barotrauma");
|
||||
|
||||
GUIMessageBox upnpBox = new GUIMessageBox("Please wait...", "Attempting UPnP port forwarding", new string[] {"Cancel"} );
|
||||
upnpBox.Buttons[0].OnClicked = upnpBox.Close;
|
||||
InitUPnP();
|
||||
|
||||
//DateTime upnpTimeout = DateTime.Now + new TimeSpan(0,0,5);
|
||||
while (server.UPnP.Status == UPnPStatus.Discovering
|
||||
&& GUIMessageBox.VisibleBox == upnpBox)// && upnpTimeout>DateTime.Now)
|
||||
while (DiscoveringUPnP())// && upnpTimeout>DateTime.Now)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
upnpBox.Close(null,null);
|
||||
|
||||
FinishUPnP();
|
||||
|
||||
#if CLIENT
|
||||
if (server.UPnP.Status == UPnPStatus.NotAvailable)
|
||||
{
|
||||
new GUIMessageBox("Error", "UPnP not available");
|
||||
@@ -225,6 +192,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
new GUIMessageBox("Error", "UPnP discovery timed out");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (isPublic)
|
||||
@@ -430,7 +398,7 @@ namespace Barotrauma.Networking
|
||||
if (startGameCoroutine != null && !CoroutineManager.IsCoroutineRunning(startGameCoroutine))
|
||||
{
|
||||
if (autoRestart) AutoRestartTimer = Math.Max(AutoRestartInterval, 5.0f);
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = true;
|
||||
GameMain.NetLobbyScreen.StartButtonEnabled = true;
|
||||
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
|
||||
@@ -441,9 +409,9 @@ namespace Barotrauma.Networking
|
||||
else if (autoRestart && Screen.Selected == GameMain.NetLobbyScreen && connectedClients.Count>0)
|
||||
{
|
||||
AutoRestartTimer -= deltaTime;
|
||||
if (AutoRestartTimer < 0.0f && GameMain.NetLobbyScreen.StartButton.Enabled)
|
||||
if (AutoRestartTimer < 0.0f && GameMain.NetLobbyScreen.StartButtonEnabled)
|
||||
{
|
||||
StartGameClicked(null,null);
|
||||
StartGame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -930,7 +898,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID);
|
||||
outmsg.Write(GameMain.NetLobbyScreen.GetServerName());
|
||||
outmsg.Write(GameMain.NetLobbyScreen.ServerMessage.Text);
|
||||
outmsg.Write(GameMain.NetLobbyScreen.ServerMessageText);
|
||||
|
||||
outmsg.Write(c.lastRecvGeneralUpdate < 1);
|
||||
if (c.lastRecvGeneralUpdate < 1)
|
||||
@@ -938,10 +906,10 @@ namespace Barotrauma.Networking
|
||||
isInitialUpdate = true;
|
||||
ClientWriteInitial(c, outmsg);
|
||||
}
|
||||
outmsg.Write((GameMain.NetLobbyScreen.SubList.SelectedData as Submarine).Name);
|
||||
outmsg.Write((GameMain.NetLobbyScreen.SubList.SelectedData as Submarine).MD5Hash.ToString());
|
||||
outmsg.Write((GameMain.NetLobbyScreen.ShuttleList.SelectedData as Submarine).Name);
|
||||
outmsg.Write((GameMain.NetLobbyScreen.ShuttleList.SelectedData as Submarine).MD5Hash.ToString());
|
||||
outmsg.Write(GameMain.NetLobbyScreen.SelectedSub.Name);
|
||||
outmsg.Write(GameMain.NetLobbyScreen.SelectedSub.MD5Hash.ToString());
|
||||
outmsg.Write(GameMain.NetLobbyScreen.SelectedShuttle.Name);
|
||||
outmsg.Write(GameMain.NetLobbyScreen.SelectedShuttle.MD5Hash.ToString());
|
||||
|
||||
outmsg.Write(Voting.AllowSubVoting);
|
||||
outmsg.Write(Voting.AllowModeVoting);
|
||||
@@ -950,7 +918,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
outmsg.WriteRangedInteger(0, Mission.MissionTypes.Count - 1, (GameMain.NetLobbyScreen.MissionTypeIndex));
|
||||
|
||||
outmsg.Write((byte)GameMain.NetLobbyScreen.ModeList.SelectedIndex);
|
||||
outmsg.Write((byte)GameMain.NetLobbyScreen.SelectedModeIndex);
|
||||
outmsg.Write(GameMain.NetLobbyScreen.LevelSeed);
|
||||
|
||||
outmsg.Write(AutoRestart);
|
||||
@@ -1015,8 +983,8 @@ namespace Barotrauma.Networking
|
||||
c.chatMsgQueue[i].ServerWrite(outmsg, c);
|
||||
}
|
||||
}
|
||||
|
||||
public bool StartGameClicked(GUIButton button, object obj)
|
||||
|
||||
public bool StartGame()
|
||||
{
|
||||
Submarine selectedSub = null;
|
||||
Submarine selectedShuttle = GameMain.NetLobbyScreen.SelectedShuttle;
|
||||
@@ -1033,13 +1001,17 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (selectedSub == null)
|
||||
{
|
||||
#if CLIENT
|
||||
GameMain.NetLobbyScreen.SubList.Flash();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedShuttle == null)
|
||||
{
|
||||
#if CLIENT
|
||||
GameMain.NetLobbyScreen.ShuttleList.Flash();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1048,7 +1020,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (selectedMode == null)
|
||||
{
|
||||
#if CLIENT
|
||||
GameMain.NetLobbyScreen.ModeList.Flash();
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1059,7 +1033,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
private IEnumerable<object> InitiateStartGame(Submarine selectedSub, Submarine selectedShuttle, GameModePreset selectedMode)
|
||||
{
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = false;
|
||||
GameMain.NetLobbyScreen.StartButtonEnabled = false;
|
||||
|
||||
if (connectedClients.Any())
|
||||
{
|
||||
@@ -1086,19 +1060,23 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (fileSender.ActiveTransfers.Count > 0)
|
||||
{
|
||||
#if CLIENT
|
||||
var msgBox = new GUIMessageBox("", "Waiting for file transfers to finish before starting the round...", new string[] { "Start now" });
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
#endif
|
||||
|
||||
float waitForTransfersTimer = 20.0f;
|
||||
while (fileSender.ActiveTransfers.Count > 0 && waitForTransfersTimer > 0.0f)
|
||||
{
|
||||
waitForTransfersTimer -= CoroutineManager.UnscaledDeltaTime;
|
||||
|
||||
#if CLIENT
|
||||
//message box close, break and start the round immediately
|
||||
if (!GUIMessageBox.MessageBoxes.Contains(msgBox))
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
@@ -1116,9 +1094,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
entityEventManager.Clear();
|
||||
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = false;
|
||||
GameMain.NetLobbyScreen.StartButtonEnabled = false;
|
||||
|
||||
#if CLIENT
|
||||
GUIMessageBox.CloseAll();
|
||||
#endif
|
||||
|
||||
roundStartSeed = DateTime.Now.Millisecond;
|
||||
Rand.SetSyncedSeed(roundStartSeed);
|
||||
@@ -1261,7 +1241,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
AddChatMessage("Press TAB to chat. Use ''r;'' to talk through the radio.", ChatMessageType.Server);
|
||||
|
||||
GameMain.NetLobbyScreen.StartButton.Enabled = true;
|
||||
GameMain.NetLobbyScreen.StartButtonEnabled = true;
|
||||
|
||||
gameStarted = true;
|
||||
initiatedStartGame = false;
|
||||
@@ -1350,7 +1330,9 @@ namespace Barotrauma.Networking
|
||||
Character.Controlled = null;
|
||||
myCharacter = null;
|
||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
#if CLIENT
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
#endif
|
||||
|
||||
entityEventManager.Clear();
|
||||
foreach (Client c in connectedClients)
|
||||
@@ -1486,7 +1468,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
client.Connection.Disconnect(targetmsg);
|
||||
|
||||
GameMain.NetLobbyScreen.RemovePlayer(client.name);
|
||||
#if CLIENT
|
||||
GameMain.NetLobbyScreen.RemovePlayer(client.name);
|
||||
#endif
|
||||
connectedClients.Remove(client);
|
||||
|
||||
UpdateVoteStatus();
|
||||
@@ -1744,85 +1728,12 @@ namespace Barotrauma.Networking
|
||||
return message;
|
||||
}
|
||||
|
||||
public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch)
|
||||
{
|
||||
base.Draw(spriteBatch);
|
||||
|
||||
if (settingsFrame != null)
|
||||
{
|
||||
settingsFrame.Draw(spriteBatch);
|
||||
}
|
||||
else if (log.LogFrame!=null)
|
||||
{
|
||||
log.LogFrame.Draw(spriteBatch);
|
||||
}
|
||||
|
||||
if (!ShowNetStats) return;
|
||||
|
||||
GUI.Font.DrawString(spriteBatch, "Unique Events: " + entityEventManager.UniqueEvents.Count, new Vector2(10, 50), Color.White);
|
||||
|
||||
int width = 200, height = 300;
|
||||
int x = GameMain.GraphicsWidth - width, y = (int)(GameMain.GraphicsHeight * 0.3f);
|
||||
|
||||
|
||||
if (clientListScrollBar == null)
|
||||
{
|
||||
clientListScrollBar = new GUIScrollBar(new Rectangle(x + width - 10, y, 10, height), "", 1.0f);
|
||||
}
|
||||
|
||||
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle(x, y, width, height), Color.Black * 0.7f, true);
|
||||
GUI.Font.DrawString(spriteBatch, "Network statistics:", new Vector2(x + 10, y + 10), Color.White);
|
||||
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Connections: "+server.ConnectionsCount, new Vector2(x + 10, y + 30), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Received bytes: " + MathUtils.GetBytesReadable(server.Statistics.ReceivedBytes), new Vector2(x + 10, y + 45), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Received packets: " + server.Statistics.ReceivedPackets, new Vector2(x + 10, y + 60), Color.White);
|
||||
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Sent bytes: " + MathUtils.GetBytesReadable(server.Statistics.SentBytes), new Vector2(x + 10, y + 75), Color.White);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Sent packets: " + server.Statistics.SentPackets, new Vector2(x + 10, y + 90), Color.White);
|
||||
|
||||
int resentMessages = 0;
|
||||
|
||||
int clientListHeight = connectedClients.Count * 40;
|
||||
float scrollBarHeight = (height - 110) / (float)Math.Max(clientListHeight, 110);
|
||||
|
||||
if (clientListScrollBar.BarSize != scrollBarHeight)
|
||||
{
|
||||
clientListScrollBar.BarSize = scrollBarHeight;
|
||||
}
|
||||
|
||||
int startY = y + 110;
|
||||
y = (startY - (int)(clientListScrollBar.BarScroll * (clientListHeight-(height - 110))));
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
Color clientColor = c.Connection.AverageRoundtripTime > 0.3f ? Color.Red : Color.White;
|
||||
|
||||
if (y >= startY && y < startY + height - 120)
|
||||
{
|
||||
GUI.SmallFont.DrawString(spriteBatch, c.name + " ("+c.Connection.RemoteEndPoint.Address.ToString()+")", new Vector2(x + 10, y), clientColor);
|
||||
GUI.SmallFont.DrawString(spriteBatch, "Ping: " + (int)(c.Connection.AverageRoundtripTime * 1000.0f) + " ms", new Vector2(x+20, y+10), clientColor);
|
||||
}
|
||||
if (y + 25 >= startY && y < startY + height - 130) GUI.SmallFont.DrawString(spriteBatch, "Resent messages: " + c.Connection.Statistics.ResentMessages, new Vector2(x + 20, y + 20), clientColor);
|
||||
|
||||
resentMessages += (int)c.Connection.Statistics.ResentMessages;
|
||||
|
||||
y += 40;
|
||||
}
|
||||
|
||||
clientListScrollBar.Update(1.0f / 60.0f);
|
||||
clientListScrollBar.Draw(spriteBatch);
|
||||
|
||||
netStats.AddValue(NetStats.NetStatType.ResentMessages, Math.Max(resentMessages, 0));
|
||||
netStats.AddValue(NetStats.NetStatType.SentBytes, server.Statistics.SentBytes);
|
||||
netStats.AddValue(NetStats.NetStatType.ReceivedBytes, server.Statistics.ReceivedBytes);
|
||||
|
||||
netStats.Draw(spriteBatch, new Rectangle(200,0,800,200), this);
|
||||
}
|
||||
|
||||
private void FileTransferChanged(FileSender.FileTransferOut transfer)
|
||||
{
|
||||
Client recipient = connectedClients.Find(c => c.Connection == transfer.Connection);
|
||||
#if CLIENT
|
||||
UpdateFileTransferIndicator(recipient);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SendCancelTransferMsg(FileSender.FileTransferOut transfer)
|
||||
@@ -1834,42 +1745,6 @@ namespace Barotrauma.Networking
|
||||
server.SendMessage(msg, transfer.Connection, NetDeliveryMethod.ReliableOrdered, transfer.SequenceChannel);
|
||||
}
|
||||
|
||||
private void UpdateFileTransferIndicator(Client client)
|
||||
{
|
||||
var transfers = fileSender.ActiveTransfers.FindAll(t => t.Connection == client.Connection);
|
||||
|
||||
var clientNameBox = GameMain.NetLobbyScreen.PlayerList.FindChild(client.name);
|
||||
|
||||
var clientInfo = clientNameBox.FindChild("filetransfer");
|
||||
if (clientInfo == null)
|
||||
{
|
||||
clientNameBox.ClearChildren();
|
||||
clientInfo = new GUIFrame(new Rectangle(0, 0, 180, 0), Color.Transparent, Alignment.TopRight, null, clientNameBox);
|
||||
clientInfo.UserData = "filetransfer";
|
||||
}
|
||||
else if (transfers.Count == 0)
|
||||
{
|
||||
clientInfo.Parent.RemoveChild(clientInfo);
|
||||
}
|
||||
|
||||
clientInfo.ClearChildren();
|
||||
|
||||
var progressBar = new GUIProgressBar(new Rectangle(0, 4, 160, clientInfo.Rect.Height - 8), Color.Green, "", 0.0f, Alignment.Left, clientInfo);
|
||||
progressBar.IsHorizontal = true;
|
||||
progressBar.ProgressGetter = () => { return transfers.Sum(t => t.Progress) / transfers.Count; };
|
||||
|
||||
var textBlock = new GUITextBlock(new Rectangle(0, 2, 160, 0), "", "", Alignment.TopLeft, Alignment.Left | Alignment.CenterY, clientInfo, true, GUI.SmallFont);
|
||||
textBlock.TextGetter = () =>
|
||||
{ return MathUtils.GetBytesReadable(transfers.Sum(t => t.SentOffset)) + " / " + MathUtils.GetBytesReadable(transfers.Sum(t => t.Data.Length)); };
|
||||
|
||||
var cancelButton = new GUIButton(new Rectangle(-5, 0, 14, 0), "X", Alignment.Right, "", clientInfo);
|
||||
cancelButton.OnClicked = (GUIButton button, object userdata) =>
|
||||
{
|
||||
transfers.ForEach(t => fileSender.CancelTransfer(t));
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
public void UpdateVoteStatus()
|
||||
{
|
||||
if (server.Connections.Count == 0|| connectedClients.Count == 0) return;
|
||||
@@ -1920,30 +1795,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
SaveClientPermissions();
|
||||
}
|
||||
|
||||
public override bool SelectCrewCharacter(Character character, GUIComponent crewFrame)
|
||||
{
|
||||
if (character == null) return false;
|
||||
|
||||
var characterFrame = crewFrame.FindChild("selectedcharacter");
|
||||
if (character != myCharacter)
|
||||
{
|
||||
var banButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Ban", Alignment.BottomRight, "", characterFrame);
|
||||
banButton.UserData = character.Name;
|
||||
banButton.OnClicked += GameMain.NetLobbyScreen.BanPlayer;
|
||||
|
||||
var rangebanButton = new GUIButton(new Rectangle(0, -25, 100, 20), "Ban range", Alignment.BottomRight, "", characterFrame);
|
||||
rangebanButton.UserData = character.Name;
|
||||
rangebanButton.OnClicked += GameMain.NetLobbyScreen.BanPlayerRange;
|
||||
|
||||
var kickButton = new GUIButton(new Rectangle(0, 0, 100, 20), "Kick", Alignment.BottomLeft, "", characterFrame);
|
||||
kickButton.UserData = character.Name;
|
||||
kickButton.OnClicked += GameMain.NetLobbyScreen.KickPlayer;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void SetClientCharacter(Client client, Character newCharacter)
|
||||
{
|
||||
if (client == null) return;
|
||||
|
||||
@@ -8,7 +8,7 @@ using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class Voting
|
||||
partial class Voting
|
||||
{
|
||||
private bool allowSubVoting, allowModeVoting;
|
||||
|
||||
@@ -16,83 +16,6 @@ namespace Barotrauma
|
||||
|
||||
public bool AllowEndVoting = true;
|
||||
|
||||
public bool AllowSubVoting
|
||||
{
|
||||
get { return allowSubVoting; }
|
||||
set
|
||||
{
|
||||
if (value == allowSubVoting) return;
|
||||
allowSubVoting = value;
|
||||
GameMain.NetLobbyScreen.SubList.Enabled = value || GameMain.Server != null;
|
||||
GameMain.NetLobbyScreen.InfoFrame.FindChild("subvotes").Visible = value;
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
UpdateVoteTexts(GameMain.Server.ConnectedClients, VoteType.Sub);
|
||||
GameMain.Server.UpdateVoteStatus();
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.NetLobbyScreen.SubList.Deselect();
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool AllowModeVoting
|
||||
{
|
||||
get { return allowModeVoting; }
|
||||
set
|
||||
{
|
||||
if (value == allowModeVoting) return;
|
||||
allowModeVoting = value;
|
||||
GameMain.NetLobbyScreen.ModeList.Enabled = value || GameMain.Server != null;
|
||||
GameMain.NetLobbyScreen.InfoFrame.FindChild("modevotes").Visible = value;
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
UpdateVoteTexts(GameMain.Server.ConnectedClients, VoteType.Mode);
|
||||
GameMain.Server.UpdateVoteStatus();
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.NetLobbyScreen.ModeList.Deselect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateVoteTexts(List<Client> clients, VoteType voteType)
|
||||
{
|
||||
GUIListBox listBox = (voteType == VoteType.Sub) ?
|
||||
GameMain.NetLobbyScreen.SubList : GameMain.NetLobbyScreen.ModeList;
|
||||
|
||||
foreach (GUIComponent comp in listBox.children)
|
||||
{
|
||||
GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock;
|
||||
if (voteText != null) comp.RemoveChild(voteText);
|
||||
}
|
||||
|
||||
List<Pair<object, int>> voteList = GetVoteList(voteType, clients);
|
||||
foreach (Pair<object, int> votable in voteList)
|
||||
{
|
||||
SetVoteText(listBox, votable.First, votable.Second);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetVoteText(GUIListBox listBox, object userData, int votes)
|
||||
{
|
||||
if (userData == null) return;
|
||||
foreach (GUIComponent comp in listBox.children)
|
||||
{
|
||||
if (comp.UserData != userData) continue;
|
||||
GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock;
|
||||
if (voteText == null)
|
||||
{
|
||||
voteText = new GUITextBlock(new Rectangle(0, 0, 30, 0), "", "", Alignment.Right, Alignment.Right, comp);
|
||||
voteText.UserData = "votes";
|
||||
}
|
||||
|
||||
voteText.Text = votes == 0 ? "" : votes.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private List<Pair<object, int>> GetVoteList(VoteType voteType, List<Client> voters)
|
||||
{
|
||||
List<Pair<object, int>> voteList = new List<Pair<object, int>>();
|
||||
@@ -146,44 +69,10 @@ namespace Barotrauma
|
||||
GameMain.NetworkMember.EndVoteCount = 0;
|
||||
GameMain.NetworkMember.EndVoteMax = 0;
|
||||
|
||||
#if CLIENT
|
||||
UpdateVoteTexts(connectedClients, VoteType.Mode);
|
||||
UpdateVoteTexts(connectedClients, VoteType.Sub);
|
||||
}
|
||||
|
||||
public void ClientWrite(NetBuffer msg, VoteType voteType, object data)
|
||||
{
|
||||
if (GameMain.Server != null) return;
|
||||
|
||||
msg.Write((byte)voteType);
|
||||
|
||||
switch (voteType)
|
||||
{
|
||||
case VoteType.Sub:
|
||||
Submarine sub = data as Submarine;
|
||||
if (sub == null) return;
|
||||
|
||||
msg.Write(sub.Name);
|
||||
break;
|
||||
case VoteType.Mode:
|
||||
GameModePreset gameMode = data as GameModePreset;
|
||||
if (gameMode == null) return;
|
||||
|
||||
msg.Write(gameMode.Name);
|
||||
break;
|
||||
case VoteType.EndRound:
|
||||
if (!(data is bool)) return;
|
||||
|
||||
msg.Write((bool)data);
|
||||
break;
|
||||
case VoteType.Kick:
|
||||
Client votedClient = data as Client;
|
||||
if (votedClient == null) return;
|
||||
|
||||
msg.Write(votedClient.ID);
|
||||
break;
|
||||
}
|
||||
|
||||
msg.WritePadBits();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ServerRead(NetIncomingMessage inc, Client sender)
|
||||
@@ -283,48 +172,5 @@ namespace Barotrauma
|
||||
msg.WritePadBits();
|
||||
}
|
||||
|
||||
public void ClientRead(NetIncomingMessage inc)
|
||||
{
|
||||
if (GameMain.Server != null) return;
|
||||
|
||||
AllowSubVoting = inc.ReadBoolean();
|
||||
if (allowSubVoting)
|
||||
{
|
||||
foreach (Submarine sub in Submarine.SavedSubmarines)
|
||||
{
|
||||
SetVoteText(GameMain.NetLobbyScreen.SubList, sub, 0);
|
||||
}
|
||||
int votableCount = inc.ReadByte();
|
||||
for (int i = 0; i < votableCount; i++)
|
||||
{
|
||||
int votes = inc.ReadByte();
|
||||
string subName = inc.ReadString();
|
||||
Submarine sub = Submarine.SavedSubmarines.Find(sm => sm.Name == subName);
|
||||
SetVoteText(GameMain.NetLobbyScreen.SubList, sub, votes);
|
||||
}
|
||||
}
|
||||
AllowModeVoting = inc.ReadBoolean();
|
||||
if (allowModeVoting)
|
||||
{
|
||||
int votableCount = inc.ReadByte();
|
||||
for (int i = 0; i < votableCount; i++)
|
||||
{
|
||||
int votes = inc.ReadByte();
|
||||
string modeName = inc.ReadString();
|
||||
GameModePreset mode = GameModePreset.list.Find(m => m.Name == modeName);
|
||||
SetVoteText(GameMain.NetLobbyScreen.ModeList, mode, votes);
|
||||
}
|
||||
}
|
||||
AllowEndVoting = inc.ReadBoolean();
|
||||
if (AllowEndVoting)
|
||||
{
|
||||
GameMain.NetworkMember.EndVoteCount = inc.ReadByte();
|
||||
GameMain.NetworkMember.EndVoteMax = inc.ReadByte();
|
||||
}
|
||||
AllowVoteKick = inc.ReadBoolean();
|
||||
|
||||
inc.ReadPadBits();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user