(d9829ac) v0.9.4.0
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Events\Missions\CombatMission.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Events\Missions\Mission.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Events\Missions\MissionMode.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Events\Missions\MissionPrefab.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Fonts\ScalableFont.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\GameMain.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\GameSession\CrewManager.cs" />
|
||||
@@ -193,7 +194,8 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\BlurEffect.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\CampaignSetupUI.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\CampaignUI.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\CharacterEditorScreen.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\CharacterEditor\CharacterEditorScreen.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\CharacterEditor\Wizard.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\CreditsPlayer.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\GameScreen.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Screens\LevelEditorScreen.cs" />
|
||||
@@ -217,6 +219,7 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sounds\SoundPlayer.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sounds\VideoSound.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sounds\VoipSound.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sprite\DecorativeSprite.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sprite\DeformableSprite.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sprite\DeformAnimations\CustomDeformation.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sprite\DeformAnimations\Inflate.cs" />
|
||||
@@ -227,9 +230,9 @@
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sprite\Sprite.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Sprite\SpriteSheet.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\StatusEffects\StatusEffect.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Traitors\TraitorMissionPrefab.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\CrossThread.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\LocalizationCSVtoXML.cs">
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\LocalizationCSVtoXML.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\MathUtils.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\OpenFileDialog.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Source\Utils\TextureLoader.cs" />
|
||||
|
||||
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("0.9.3.2")]
|
||||
[assembly: AssemblyFileVersion("0.9.3.2")]
|
||||
[assembly: AssemblyVersion("0.9.4.0")]
|
||||
[assembly: AssemblyFileVersion("0.9.4.0")]
|
||||
|
||||
@@ -45,9 +45,6 @@ namespace Barotrauma
|
||||
case AIState.Eat:
|
||||
stateColor = Color.Brown;
|
||||
break;
|
||||
case AIState.GoTo:
|
||||
stateColor = Color.Magenta;
|
||||
break;
|
||||
}
|
||||
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 80.0f, State.ToString(), stateColor, Color.Black);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Barotrauma
|
||||
{
|
||||
/*if (GameMain.GameSession != null && GameMain.GameSession.CrewManager != null)
|
||||
{
|
||||
CurrentOrder = Order.PrefabList.Find(o => o.AITag == "dismissed");
|
||||
CurrentOrder = Order.GetPrefab("dismissed");
|
||||
objectiveManager.SetOrder(CurrentOrder, "", null);
|
||||
GameMain.GameSession.CrewManager.SetCharacterOrder(Character, CurrentOrder, null, null);
|
||||
}*/
|
||||
|
||||
@@ -369,12 +369,12 @@ namespace Barotrauma
|
||||
LimbJoints.ForEach(j => j.UpdateDeformations(deltaTime));
|
||||
foreach (var deformation in SpriteDeformations)
|
||||
{
|
||||
if (character.IsDead && deformation.DeformationParams.StopWhenHostIsDead) { continue; }
|
||||
if (deformation.DeformationParams.UseMovementSine)
|
||||
if (character.IsDead && deformation.Params.StopWhenHostIsDead) { continue; }
|
||||
if (deformation.Params.UseMovementSine)
|
||||
{
|
||||
if (this is AnimController animator)
|
||||
{
|
||||
deformation.Phase = MathUtils.WrapAngleTwoPi(animator.WalkPos * deformation.DeformationParams.Frequency + MathHelper.Pi * deformation.DeformationParams.SineOffset);
|
||||
deformation.Phase = MathUtils.WrapAngleTwoPi(animator.WalkPos * deformation.Params.Frequency + MathHelper.Pi * deformation.Params.SineOffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -7,10 +7,8 @@ namespace Barotrauma
|
||||
{
|
||||
partial class Attack
|
||||
{
|
||||
public string StructureSoundType
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
[Serialize("StructureBlunt", true), Editable()]
|
||||
public string StructureSoundType { get; private set; }
|
||||
|
||||
private RoundSound sound;
|
||||
|
||||
@@ -23,8 +21,6 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError("Error in attack ("+element+") - sounds should be defined as child elements, not as attributes.");
|
||||
return;
|
||||
}
|
||||
|
||||
StructureSoundType = element.GetAttributeString("structuresoundtype", "StructureBlunt");
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
|
||||
@@ -86,11 +86,7 @@ namespace Barotrauma
|
||||
set { chromaticAberrationStrength = MathHelper.Clamp(value, 0.0f, 100.0f); }
|
||||
}
|
||||
|
||||
public string BloodDecalName
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
public string BloodDecalName => Params.BloodDecal;
|
||||
|
||||
private List<ParticleEmitter> bloodEmitters = new List<ParticleEmitter>();
|
||||
public IEnumerable<ParticleEmitter> BloodEmitters
|
||||
@@ -137,22 +133,18 @@ namespace Barotrauma
|
||||
get { return activeObjectiveEntities; }
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XDocument doc)
|
||||
partial void InitProjSpecific(XElement mainElement)
|
||||
{
|
||||
soundInterval = doc.Root.GetAttributeFloat("soundinterval", 10.0f);
|
||||
soundInterval = mainElement.GetAttributeFloat("soundinterval", 10.0f);
|
||||
soundTimer = Rand.Range(0.0f, soundInterval);
|
||||
|
||||
BloodDecalName = doc.Root.GetAttributeString("blooddecal", "");
|
||||
|
||||
sounds = new List<CharacterSound>();
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
Params.Sounds.ForEach(s => sounds.Add(new CharacterSound(s)));
|
||||
|
||||
foreach (XElement subElement in mainElement.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "sound":
|
||||
var characterSound = new CharacterSound(subElement);
|
||||
if (characterSound.Sound != null) { sounds.Add(characterSound); }
|
||||
break;
|
||||
case "damageemitter":
|
||||
damageEmitters.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
@@ -216,7 +208,7 @@ namespace Barotrauma
|
||||
float targetOffsetAmount = 0.0f;
|
||||
if (moveCam)
|
||||
{
|
||||
if (needsAir &&
|
||||
if (NeedsAir &&
|
||||
pressureProtection < 80.0f &&
|
||||
(AnimController.CurrentHull == null || AnimController.CurrentHull.LethalPressure > 0.0f))
|
||||
{
|
||||
@@ -351,7 +343,7 @@ namespace Barotrauma
|
||||
|
||||
partial void OnAttackedProjSpecific(Character attacker, AttackResult attackResult)
|
||||
{
|
||||
if (attackResult.Damage <= 0) { return; }
|
||||
if (attackResult.Damage <= 1.0f) { return; }
|
||||
if (soundTimer < soundInterval * 0.5f)
|
||||
{
|
||||
PlaySound(CharacterSound.SoundType.Damage);
|
||||
@@ -542,7 +534,7 @@ namespace Barotrauma
|
||||
{
|
||||
switch (AIController.State)
|
||||
{
|
||||
case AIController.AIState.Attack:
|
||||
case AIState.Attack:
|
||||
PlaySound(CharacterSound.SoundType.Attack);
|
||||
break;
|
||||
default:
|
||||
@@ -577,6 +569,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
CharacterHealth.UpdateClientSpecific(deltaTime);
|
||||
if (controlled == this)
|
||||
{
|
||||
CharacterHealth.UpdateHUD(deltaTime);
|
||||
@@ -612,7 +605,7 @@ namespace Barotrauma
|
||||
CharacterHUD.Draw(spriteBatch, this, cam);
|
||||
if (drawHealth) CharacterHealth.DrawHUD(spriteBatch);
|
||||
}
|
||||
|
||||
|
||||
public virtual void DrawFront(SpriteBatch spriteBatch, Camera cam)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
@@ -713,12 +706,14 @@ namespace Barotrauma
|
||||
|
||||
if (IsDead) return;
|
||||
|
||||
if (Vitality < MaxVitality * 0.98f && hudInfoVisible)
|
||||
if (CharacterHealth.DisplayedVitality < MaxVitality * 0.98f && hudInfoVisible)
|
||||
{
|
||||
hudInfoAlpha = Math.Max(hudInfoAlpha, Math.Min(CharacterHealth.DamageOverlayTimer, 1.0f));
|
||||
|
||||
Vector2 healthBarPos = new Vector2(pos.X - 50, -pos.Y);
|
||||
GUI.DrawProgressBar(spriteBatch, healthBarPos, new Vector2(100.0f, 15.0f),
|
||||
Vitality / MaxVitality,
|
||||
Color.Lerp(Color.Red, Color.Green, Vitality / MaxVitality) * 0.8f * hudInfoAlpha,
|
||||
CharacterHealth.DisplayedVitality / MaxVitality,
|
||||
Color.Lerp(Color.Red, Color.Green, CharacterHealth.DisplayedVitality / MaxVitality) * 0.8f * hudInfoAlpha,
|
||||
new Color(0.5f, 0.57f, 0.6f, 1.0f) * hudInfoAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
public static CharacterInfo ClientRead(string configPath, IReadMessage inc)
|
||||
public static CharacterInfo ClientRead(string speciesName, IReadMessage inc)
|
||||
{
|
||||
ushort infoID = inc.ReadUInt16();
|
||||
string newName = inc.ReadString();
|
||||
@@ -238,7 +238,7 @@ namespace Barotrauma
|
||||
Dictionary<string, float> skillLevels = new Dictionary<string, float>();
|
||||
if (!string.IsNullOrEmpty(jobIdentifier))
|
||||
{
|
||||
jobPrefab = JobPrefab.List.Find(jp => jp.Identifier == jobIdentifier);
|
||||
jobPrefab = JobPrefab.Get(jobIdentifier);
|
||||
byte skillCount = inc.ReadByte();
|
||||
for (int i = 0; i < skillCount; i++)
|
||||
{
|
||||
@@ -249,7 +249,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
// TODO: animations
|
||||
CharacterInfo ch = new CharacterInfo(configPath, newName, jobPrefab, ragdollFile)
|
||||
CharacterInfo ch = new CharacterInfo(speciesName, newName, jobPrefab, ragdollFile)
|
||||
{
|
||||
ID = infoID,
|
||||
};
|
||||
|
||||
@@ -20,13 +20,13 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
//freeze AI characters if more than 1 seconds have passed since last update from the server
|
||||
if (lastRecvPositionUpdateTime < Lidgren.Network.NetTime.Now - 1.0f)
|
||||
//freeze AI characters if more than x seconds have passed since last update from the server
|
||||
if (lastRecvPositionUpdateTime < Lidgren.Network.NetTime.Now - NetConfig.FreezeCharacterIfPositionDataMissingDelay)
|
||||
{
|
||||
AnimController.Frozen = true;
|
||||
memState.Clear();
|
||||
//hide after 2 seconds
|
||||
if (lastRecvPositionUpdateTime < Lidgren.Network.NetTime.Now - 2.0f)
|
||||
//hide after y seconds
|
||||
if (lastRecvPositionUpdateTime < Lidgren.Network.NetTime.Now - NetConfig.DisableCharacterIfPositionDataMissingDelay)
|
||||
{
|
||||
Enabled = false;
|
||||
return;
|
||||
@@ -74,7 +74,7 @@ namespace Barotrauma
|
||||
states = newInput,
|
||||
intAim = intAngle
|
||||
};
|
||||
if (focusedItem != null && !CharacterInventory.DraggingItemToWorld &&
|
||||
if (focusedItem != null && !CharacterInventory.DraggingItemToWorld &&
|
||||
(!newMem.states.HasFlag(InputNetFlags.Grab) && !newMem.states.HasFlag(InputNetFlags.Health)))
|
||||
{
|
||||
newMem.interact = focusedItem.ID;
|
||||
@@ -133,9 +133,9 @@ namespace Barotrauma
|
||||
{
|
||||
msg.WriteRangedInteger((int)memInput[i].states, 0, (int)InputNetFlags.MaxVal);
|
||||
msg.Write(memInput[i].intAim);
|
||||
if (memInput[i].states.HasFlag(InputNetFlags.Select) ||
|
||||
if (memInput[i].states.HasFlag(InputNetFlags.Select) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Deselect) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Use) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Use) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Health) ||
|
||||
memInput[i].states.HasFlag(InputNetFlags.Grab))
|
||||
{
|
||||
@@ -187,11 +187,11 @@ namespace Barotrauma
|
||||
bool attackInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Attack].Held = attackInput;
|
||||
keys[(int)InputType.Attack].SetState(false, attackInput);
|
||||
|
||||
|
||||
double aimAngle = msg.ReadUInt16() / 65535.0 * 2.0 * Math.PI;
|
||||
cursorPosition = AimRefPosition + new Vector2((float)Math.Cos(aimAngle), (float)Math.Sin(aimAngle)) * 500.0f;
|
||||
TransformCursorPos();
|
||||
|
||||
|
||||
bool ragdollInput = msg.ReadBoolean();
|
||||
keys[(int)InputType.Ragdoll].Held = ragdollInput;
|
||||
keys[(int)InputType.Ragdoll].SetState(false, ragdollInput);
|
||||
@@ -225,7 +225,7 @@ namespace Barotrauma
|
||||
msg.ReadSingle());
|
||||
float MaxVel = NetConfig.MaxPhysicsBodyVelocity;
|
||||
Vector2 linearVelocity = new Vector2(
|
||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
|
||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
|
||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
|
||||
linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12);
|
||||
|
||||
@@ -252,9 +252,9 @@ namespace Barotrauma
|
||||
if (GameMain.Client.Character == this && AllowInput)
|
||||
{
|
||||
var posInfo = new CharacterStateInfo(
|
||||
pos, rotation,
|
||||
networkUpdateID,
|
||||
facingRight ? Direction.Right : Direction.Left,
|
||||
pos, rotation,
|
||||
networkUpdateID,
|
||||
facingRight ? Direction.Right : Direction.Left,
|
||||
selectedCharacter, selectedItem, animation);
|
||||
|
||||
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
|
||||
@@ -264,11 +264,11 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
var posInfo = new CharacterStateInfo(
|
||||
pos, rotation,
|
||||
linearVelocity, angularVelocity,
|
||||
sendingTime, facingRight ? Direction.Right : Direction.Left,
|
||||
pos, rotation,
|
||||
linearVelocity, angularVelocity,
|
||||
sendingTime, facingRight ? Direction.Right : Direction.Left,
|
||||
selectedCharacter, selectedItem, animation);
|
||||
|
||||
|
||||
while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
|
||||
index++;
|
||||
memState.Insert(index, posInfo);
|
||||
@@ -359,18 +359,12 @@ namespace Barotrauma
|
||||
|
||||
DebugConsole.Log("Received spawn data for " + speciesName);
|
||||
|
||||
string configPath = GetConfigFile(speciesName);
|
||||
if (string.IsNullOrEmpty(configPath))
|
||||
{
|
||||
throw new Exception("Error in character spawn data - could not find a config file for the character \"" + configPath + "\"!");
|
||||
}
|
||||
|
||||
Character character = null;
|
||||
if (noInfo)
|
||||
{
|
||||
if (!spawn) return null;
|
||||
|
||||
character = Create(configPath, position, seed, null, true);
|
||||
character = Create(speciesName, position, seed, null, true);
|
||||
character.ID = id;
|
||||
}
|
||||
else
|
||||
@@ -383,19 +377,13 @@ namespace Barotrauma
|
||||
|
||||
if (!spawn) return null;
|
||||
|
||||
string infoConfigPath = GetConfigFile(infoSpeciesName);
|
||||
if (string.IsNullOrEmpty(infoConfigPath))
|
||||
{
|
||||
throw new Exception("Error in character spawn data - could not find a config file for the character info \"" + configPath + "\"!");
|
||||
}
|
||||
CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc);
|
||||
|
||||
CharacterInfo info = CharacterInfo.ClientRead(infoConfigPath, inc);
|
||||
|
||||
character = Create(configPath, position, seed, info, GameMain.Client.ID != ownerId, hasAi);
|
||||
character = Create(infoSpeciesName, position, seed, info, GameMain.Client.ID != ownerId, hasAi);
|
||||
character.ID = id;
|
||||
character.TeamID = (TeamType)teamID;
|
||||
|
||||
if (configPath == HumanConfigFile && character.TeamID != TeamType.FriendlyNPC)
|
||||
if (character.IsHuman && character.TeamID != TeamType.FriendlyNPC)
|
||||
{
|
||||
CharacterInfo duplicateCharacterInfo = GameMain.GameSession.CrewManager.GetCharacterInfos().FirstOrDefault(c => c.ID == info.ID);
|
||||
GameMain.GameSession.CrewManager.RemoveCharacterInfo(duplicateCharacterInfo);
|
||||
@@ -421,15 +409,6 @@ namespace Barotrauma
|
||||
return character;
|
||||
}
|
||||
|
||||
private void ReadTraitorStatus(IReadMessage msg)
|
||||
{
|
||||
IsTraitor = msg.ReadBoolean();
|
||||
if (IsTraitor)
|
||||
{
|
||||
TraitorCurrentObjective = msg.ReadString();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadStatus(IReadMessage msg)
|
||||
{
|
||||
bool isDead = msg.ReadBoolean();
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Sounds;
|
||||
using Barotrauma.Sounds;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -12,29 +10,18 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private readonly RoundSound roundSound;
|
||||
public readonly CharacterParams.SoundParams Params;
|
||||
|
||||
public readonly SoundType Type;
|
||||
public SoundType Type => Params.State;
|
||||
public Gender Gender => Params.Gender;
|
||||
public float Volume => roundSound.Volume;
|
||||
public float Range => roundSound.Range;
|
||||
public Sound Sound => roundSound?.Sound;
|
||||
|
||||
public float Volume
|
||||
public CharacterSound(CharacterParams.SoundParams soundParams)
|
||||
{
|
||||
get { return roundSound.Volume; }
|
||||
}
|
||||
public float Range
|
||||
{
|
||||
get { return roundSound.Range; }
|
||||
}
|
||||
public Sound Sound
|
||||
{
|
||||
get { return roundSound?.Sound; }
|
||||
}
|
||||
|
||||
public readonly Gender Gender;
|
||||
|
||||
public CharacterSound(XElement element)
|
||||
{
|
||||
roundSound = Submarine.LoadRoundSound(element);
|
||||
Enum.TryParse(element.GetAttributeString("state", "Idle"), true, out Type);
|
||||
Enum.TryParse(element.GetAttributeString("gender", "None"), true, out Gender);
|
||||
Params = soundParams;
|
||||
roundSound = Submarine.LoadRoundSound(soundParams.Element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,8 @@ namespace Barotrauma
|
||||
private const float UpdateDisplayedAfflictionsInterval = 0.5f;
|
||||
private List<Affliction> currentDisplayedAfflictions = new List<Affliction>();
|
||||
|
||||
public float DisplayedVitality, DisplayVitalityDelay;
|
||||
|
||||
public bool MouseOnElement
|
||||
{
|
||||
get { return highlightedLimbIndex > -1 || GUI.MouseOn == dropItemArea; }
|
||||
@@ -159,6 +161,8 @@ namespace Barotrauma
|
||||
|
||||
partial void InitProjSpecific(XElement element, Character character)
|
||||
{
|
||||
DisplayedVitality = MaxVitality;
|
||||
|
||||
if (strengthTexts == null)
|
||||
{
|
||||
strengthTexts = new string[]
|
||||
@@ -349,15 +353,17 @@ namespace Barotrauma
|
||||
|
||||
private void OnAttacked(Character attacker, AttackResult attackResult)
|
||||
{
|
||||
if (Math.Abs(attackResult.Damage) < 0.01f && attackResult.Afflictions.Count == 0) return;
|
||||
if (Math.Abs(attackResult.Damage) < 0.01f && attackResult.Afflictions.Count == 0) { return; }
|
||||
DamageOverlayTimer = MathHelper.Clamp(attackResult.Damage / MaxVitality, DamageOverlayTimer, 1.0f);
|
||||
if (healthShadowDelay <= 0.0f) healthShadowDelay = 1.0f;
|
||||
if (healthShadowDelay <= 0.0f) { healthShadowDelay = 1.0f; }
|
||||
|
||||
if (healthBarPulsateTimer <= 0.0f) healthBarPulsatePhase = 0.0f;
|
||||
if (healthBarPulsateTimer <= 0.0f) { healthBarPulsatePhase = 0.0f; }
|
||||
healthBarPulsateTimer = 1.0f;
|
||||
|
||||
float additionalIntensity = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, 0.1f, attackResult.Damage / MaxVitality));
|
||||
damageIntensity = MathHelper.Clamp(damageIntensity + additionalIntensity, 0, 1);
|
||||
|
||||
DisplayVitalityDelay = 0.5f;
|
||||
}
|
||||
|
||||
private void UpdateAlignment()
|
||||
@@ -435,6 +441,35 @@ namespace Barotrauma
|
||||
uiScale = GUI.Scale;
|
||||
}
|
||||
|
||||
public void UpdateClientSpecific(float deltaTime)
|
||||
{
|
||||
if (GameMain.NetworkMember == null)
|
||||
{
|
||||
DisplayedVitality = Vitality;
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayVitalityDelay -= deltaTime;
|
||||
if (DisplayVitalityDelay <= 0.0f)
|
||||
{
|
||||
DisplayedVitality = Vitality;
|
||||
}
|
||||
}
|
||||
|
||||
if (damageIntensity > 0)
|
||||
{
|
||||
damageIntensity -= deltaTime * damageIntensityDropdownRate;
|
||||
if (damageIntensity < 0)
|
||||
{
|
||||
damageIntensity = 0;
|
||||
}
|
||||
}
|
||||
if (DamageOverlayTimer > 0.0f)
|
||||
{
|
||||
DamageOverlayTimer -= deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateOxygenProjSpecific(float prevOxygen)
|
||||
{
|
||||
if (prevOxygen > 0.0f && OxygenAmount <= 0.0f &&
|
||||
@@ -492,20 +527,7 @@ namespace Barotrauma
|
||||
});
|
||||
updateDisplayedAfflictionsTimer = UpdateDisplayedAfflictionsInterval;
|
||||
}
|
||||
|
||||
if (DamageOverlayTimer > 0.0f)
|
||||
{
|
||||
DamageOverlayTimer -= deltaTime;
|
||||
}
|
||||
if (damageIntensity > 0)
|
||||
{
|
||||
damageIntensity -= deltaTime * damageIntensityDropdownRate;
|
||||
if (damageIntensity < 0)
|
||||
{
|
||||
damageIntensity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (healthShadowDelay > 0.0f)
|
||||
{
|
||||
healthShadowDelay -= deltaTime;
|
||||
@@ -639,12 +661,12 @@ namespace Barotrauma
|
||||
}
|
||||
else
|
||||
{
|
||||
healthBar.Color = healthWindowHealthBar.Color = ToolBox.GradientLerp(Vitality / MaxVitality, Color.Red, Color.Orange, Color.Green);
|
||||
healthBar.Color = healthWindowHealthBar.Color = ToolBox.GradientLerp(DisplayedVitality / MaxVitality, Color.Red, Color.Orange, Color.Green);
|
||||
healthBar.HoverColor = healthWindowHealthBar.HoverColor = healthBar.Color * 2.0f;
|
||||
healthBar.BarSize = healthWindowHealthBar.BarSize =
|
||||
(Vitality > 0.0f) ?
|
||||
(MaxVitality > 0.0f ? Vitality / MaxVitality : 0.0f) :
|
||||
(Math.Abs(MinVitality) > 0.0f ? 1.0f - Vitality / MinVitality : 0.0f);
|
||||
(DisplayedVitality > 0.0f) ?
|
||||
(MaxVitality > 0.0f ? DisplayedVitality / MaxVitality : 0.0f) :
|
||||
(Math.Abs(MinVitality) > 0.0f ? 1.0f - DisplayedVitality / MinVitality : 0.0f);
|
||||
|
||||
if (healthBarPulsateTimer > 0.0f)
|
||||
{
|
||||
@@ -1446,6 +1468,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CalculateVitality();
|
||||
DisplayedVitality = Vitality;
|
||||
}
|
||||
|
||||
partial void UpdateLimbAfflictionOverlays()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -29,13 +30,18 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
var itemContainer = new GUILayoutGroup(new RectTransform(new Vector2(0.45f, 0.5f), paddedFrame.RectTransform, Anchor.TopRight)
|
||||
{ RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) });
|
||||
{ RelativeOffset = new Vector2(0.0f, 0.2f + descriptionBlock.RectTransform.RelativeSize.Y) })
|
||||
{
|
||||
Stretch = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform),
|
||||
TextManager.Get("Items", fallBackTag: "mapentitycategory.equipment"), font: GUI.LargeFont);
|
||||
foreach (string itemName in ItemNames)
|
||||
foreach (string itemName in ItemNames.Distinct())
|
||||
{
|
||||
int count = ItemNames.Count(i => i == itemName);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), itemContainer.RectTransform),
|
||||
" - " + itemName, font: GUI.SmallFont);
|
||||
" - " + (count == 1 ? itemName : itemName + " x" + count),
|
||||
font: GUI.SmallFont);
|
||||
}
|
||||
|
||||
return backFrame;
|
||||
|
||||
@@ -11,6 +11,8 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using SpriteParams = Barotrauma.RagdollParams.SpriteParams;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -18,8 +20,9 @@ namespace Barotrauma
|
||||
{
|
||||
public void UpdateDeformations(float deltaTime)
|
||||
{
|
||||
float jointMidAngle = (LowerLimit + UpperLimit) / 2.0f;
|
||||
float jointAngle = this.JointAngle - jointMidAngle;
|
||||
float diff = Math.Abs(UpperLimit - LowerLimit);
|
||||
float strength = MathHelper.Lerp(0, 1, MathUtils.InverseLerp(0, MathHelper.Pi, diff));
|
||||
float jointAngle = this.JointAngle * strength;
|
||||
|
||||
JointBendDeformation limbADeformation = LimbA.Deformations.Find(d => d is JointBendDeformation) as JointBendDeformation;
|
||||
JointBendDeformation limbBDeformation = LimbB.Deformations.Find(d => d is JointBendDeformation) as JointBendDeformation;
|
||||
@@ -28,7 +31,6 @@ namespace Barotrauma
|
||||
{
|
||||
UpdateBend(LimbA, limbADeformation, this.LocalAnchorA, -jointAngle);
|
||||
UpdateBend(LimbB, limbBDeformation, this.LocalAnchorB, jointAngle);
|
||||
|
||||
}
|
||||
|
||||
void UpdateBend(Limb limb, JointBendDeformation deformation, Vector2 localAnchor, float angle)
|
||||
@@ -74,6 +76,14 @@ namespace Barotrauma
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch)
|
||||
{
|
||||
// TODO: move this into the character editor
|
||||
//var mouthPos = ragdoll.GetMouthPosition();
|
||||
//if (mouthPos != null)
|
||||
//{
|
||||
// var pos = ConvertUnits.ToDisplayUnits(mouthPos.Value);
|
||||
// pos.Y = -pos.Y;
|
||||
// ShapeExtensions.DrawPoint(spriteBatch, pos, Color.Red, size: 5);
|
||||
//}
|
||||
return;
|
||||
// A debug visualisation on the bezier curve between limbs.
|
||||
var start = LimbA.WorldPosition;
|
||||
@@ -110,6 +120,9 @@ namespace Barotrauma
|
||||
|
||||
public Sprite Sprite { get; protected set; }
|
||||
public DeformableSprite DeformSprite { get; protected set; }
|
||||
|
||||
public List<DecorativeSprite> DecorativeSprites { get; private set; } = new List<DecorativeSprite>();
|
||||
|
||||
public Sprite ActiveSprite
|
||||
{
|
||||
get
|
||||
@@ -130,32 +143,23 @@ namespace Barotrauma
|
||||
public WearableSprite HuskSprite { get; private set; }
|
||||
public WearableSprite HerpesSprite { get; private set; }
|
||||
|
||||
public void LoadHuskSprite()
|
||||
{
|
||||
var info = character.Info;
|
||||
if (info == null) { return; }
|
||||
var element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), WearableType.Husk).FirstOrDefault();
|
||||
if (element != null)
|
||||
{
|
||||
HuskSprite = new WearableSprite(element.Element("sprite"), WearableType.Husk);
|
||||
}
|
||||
}
|
||||
public void LoadHerpesSprite()
|
||||
{
|
||||
var info = character.Info;
|
||||
if (info == null) { return; }
|
||||
var element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), WearableType.Herpes).FirstOrDefault();
|
||||
if (element != null)
|
||||
{
|
||||
HerpesSprite = new WearableSprite(element.Element("sprite"), WearableType.Herpes);
|
||||
}
|
||||
}
|
||||
public void LoadHuskSprite() => HuskSprite = GetWearableSprite(WearableType.Husk);
|
||||
public void LoadHerpesSprite() => HerpesSprite = GetWearableSprite(WearableType.Herpes);
|
||||
|
||||
public float TextureScale => limbParams.Ragdoll.TextureScale;
|
||||
public float TextureScale => Params.Ragdoll.TextureScale;
|
||||
|
||||
public Sprite DamagedSprite { get; private set; }
|
||||
|
||||
public List<ConditionalSprite> ConditionalSprites { get; private set; } = new List<ConditionalSprite>();
|
||||
private Dictionary<DecorativeSprite, SpriteState> spriteAnimState = new Dictionary<DecorativeSprite, SpriteState>();
|
||||
private Dictionary<int, List<DecorativeSprite>> DecorativeSpriteGroups = new Dictionary<int, List<DecorativeSprite>>();
|
||||
|
||||
class SpriteState
|
||||
{
|
||||
public float RotationState;
|
||||
public float OffsetState;
|
||||
public bool IsActive = true;
|
||||
}
|
||||
|
||||
public Color InitialLightSourceColor
|
||||
{
|
||||
@@ -183,25 +187,38 @@ namespace Barotrauma
|
||||
set { burnOverLayStrength = MathHelper.Clamp(value, 0.0f, 100.0f); }
|
||||
}
|
||||
|
||||
public string HitSoundTag { get; private set; }
|
||||
public string HitSoundTag => Params?.Sound?.Tag;
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
for (int i = 0; i < Params.decorativeSpriteParams.Count; i++)
|
||||
{
|
||||
var param = Params.decorativeSpriteParams[i];
|
||||
var decorativeSprite = new DecorativeSprite(param.Element, file: GetSpritePath(param.Element, param));
|
||||
DecorativeSprites.Add(decorativeSprite);
|
||||
int groupID = decorativeSprite.RandomGroupID;
|
||||
if (!DecorativeSpriteGroups.ContainsKey(groupID))
|
||||
{
|
||||
DecorativeSpriteGroups.Add(groupID, new List<DecorativeSprite>());
|
||||
}
|
||||
DecorativeSpriteGroups[groupID].Add(decorativeSprite);
|
||||
spriteAnimState.Add(decorativeSprite, new SpriteState());
|
||||
}
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "sprite":
|
||||
Sprite = new Sprite(subElement, "", GetSpritePath(subElement));
|
||||
Sprite = new Sprite(subElement, file: GetSpritePath(subElement, Params.normalSpriteParams));
|
||||
break;
|
||||
case "damagedsprite":
|
||||
DamagedSprite = new Sprite(subElement, "", GetSpritePath(subElement));
|
||||
DamagedSprite = new Sprite(subElement, file: GetSpritePath(subElement, Params.damagedSpriteParams));
|
||||
break;
|
||||
case "conditionalsprite":
|
||||
ConditionalSprites.Add(new ConditionalSprite(subElement, character, file: GetSpritePath(subElement)));
|
||||
ConditionalSprites.Add(new ConditionalSprite(subElement, character, file: GetSpritePath(subElement, null)));
|
||||
break;
|
||||
case "deformablesprite":
|
||||
DeformSprite = new DeformableSprite(subElement, filePath: GetSpritePath(subElement));
|
||||
DeformSprite = new DeformableSprite(subElement, filePath: GetSpritePath(subElement, Params.deformSpriteParams));
|
||||
foreach (XElement animationElement in subElement.Elements())
|
||||
{
|
||||
int sync = animationElement.GetAttributeInt("sync", -1);
|
||||
@@ -231,32 +248,63 @@ namespace Barotrauma
|
||||
LightSource = new LightSource(subElement);
|
||||
InitialLightSourceColor = LightSource.Color;
|
||||
break;
|
||||
case "sound":
|
||||
HitSoundTag = subElement.GetAttributeString("tag", "");
|
||||
if (string.IsNullOrWhiteSpace(HitSoundTag))
|
||||
{
|
||||
//legacy support
|
||||
HitSoundTag = subElement.GetAttributeString("file", "");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RecreateSprite()
|
||||
public void RecreateSprites()
|
||||
{
|
||||
if (Sprite == null) { return; }
|
||||
Sprite.Remove();
|
||||
var source = Sprite.SourceElement;
|
||||
Sprite = new Sprite(source, file: GetSpritePath(source));
|
||||
if (Sprite != null)
|
||||
{
|
||||
Sprite.Remove();
|
||||
var source = Sprite.SourceElement;
|
||||
Sprite = new Sprite(source, file: GetSpritePath(source, Params.normalSpriteParams));
|
||||
}
|
||||
if (DeformSprite != null)
|
||||
{
|
||||
DeformSprite.Remove();
|
||||
var source = DeformSprite.Sprite.SourceElement;
|
||||
DeformSprite = new DeformableSprite(source, filePath: GetSpritePath(source, Params.deformSpriteParams));
|
||||
}
|
||||
if (DamagedSprite != null)
|
||||
{
|
||||
DamagedSprite.Remove();
|
||||
var source = DamagedSprite.SourceElement;
|
||||
DamagedSprite = new Sprite(source, file: GetSpritePath(source, Params.damagedSpriteParams));
|
||||
}
|
||||
for (int i = 0; i < ConditionalSprites.Count; i++)
|
||||
{
|
||||
var conditionalSprite = ConditionalSprites[i];
|
||||
conditionalSprite.Remove();
|
||||
var source = conditionalSprite.SourceElement;
|
||||
// TODO: lazy load?
|
||||
ConditionalSprites[i] = new ConditionalSprite(source, character, file: GetSpritePath(source, null));
|
||||
}
|
||||
for (int i = 0; i < DecorativeSprites.Count; i++)
|
||||
{
|
||||
var decorativeSprite = DecorativeSprites[i];
|
||||
decorativeSprite.Remove();
|
||||
var source = decorativeSprite.Sprite.SourceElement;
|
||||
DecorativeSprites[i] = new DecorativeSprite(source, file: GetSpritePath(source, Params.decorativeSpriteParams[i]));
|
||||
}
|
||||
}
|
||||
|
||||
private string GetSpritePath(XElement element, SpriteParams spriteParams)
|
||||
{
|
||||
string texturePath = element.GetAttributeString("texture", null);
|
||||
if (string.IsNullOrWhiteSpace(texturePath) && spriteParams != null)
|
||||
{
|
||||
texturePath = spriteParams.Ragdoll.Texture;
|
||||
}
|
||||
return GetSpritePath(texturePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the full path of a limb sprite, taking into account tags, gender and head id
|
||||
/// </summary>
|
||||
private string GetSpritePath(XElement element)
|
||||
private string GetSpritePath(string texturePath)
|
||||
{
|
||||
string spritePath = element.Attribute("texture")?.Value ?? "";
|
||||
string spritePath = texturePath;
|
||||
string spritePathWithTags = spritePath;
|
||||
if (character.Info != null && character.IsHumanoid)
|
||||
{
|
||||
@@ -274,16 +322,19 @@ namespace Barotrauma
|
||||
Path.GetFileNameWithoutExtension(spritePath) + tags + Path.GetExtension(spritePath));
|
||||
}
|
||||
}
|
||||
|
||||
return File.Exists(spritePathWithTags) ? spritePathWithTags : spritePath;
|
||||
}
|
||||
|
||||
partial void LoadParamsProjSpecific()
|
||||
{
|
||||
bool isFlipped = dir == Direction.Left;
|
||||
Sprite?.LoadParams(limbParams.normalSpriteParams, isFlipped);
|
||||
DamagedSprite?.LoadParams(limbParams.damagedSpriteParams, isFlipped);
|
||||
DeformSprite?.Sprite.LoadParams(limbParams.deformSpriteParams, isFlipped);
|
||||
Sprite?.LoadParams(Params.normalSpriteParams, isFlipped);
|
||||
DamagedSprite?.LoadParams(Params.damagedSpriteParams, isFlipped);
|
||||
DeformSprite?.Sprite.LoadParams(Params.deformSpriteParams, isFlipped);
|
||||
for (int i = 0; i < DecorativeSprites.Count; i++)
|
||||
{
|
||||
DecorativeSprites[i].Sprite?.LoadParams(Params.decorativeSpriteParams[i], isFlipped);
|
||||
}
|
||||
}
|
||||
|
||||
partial void AddDamageProjSpecific(Vector2 simPosition, List<Affliction> afflictions, bool playSound, List<DamageModifier> appliedDamageModifiers)
|
||||
@@ -378,6 +429,8 @@ namespace Barotrauma
|
||||
LightSource.ParentSub = body.Submarine;
|
||||
LightSource.Rotation = (dir == Direction.Right) ? body.Rotation : body.Rotation - MathHelper.Pi;
|
||||
}
|
||||
|
||||
UpdateSpriteStates(deltaTime);
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, Camera cam, Color? overrideColor = null)
|
||||
@@ -401,7 +454,14 @@ namespace Barotrauma
|
||||
|
||||
body.Dir = Dir;
|
||||
|
||||
bool hideLimb = wearingItems.Any(w => w != null && w.HideLimb);
|
||||
bool enableHuskSprite = character.IsHusk || character.CharacterHealth.GetAffliction<AfflictionHusk>("huskinfection")?.State == AfflictionHusk.InfectionState.Active;
|
||||
float herpesStrength = character.CharacterHealth.GetAfflictionStrength("spaceherpes");
|
||||
|
||||
bool hideLimb = Params.Hide ||
|
||||
enableHuskSprite && HuskSprite != null && HuskSprite.HideLimb ||
|
||||
OtherWearables.Any(w => w.HideLimb) ||
|
||||
wearingItems.Any(w => w != null && w.HideLimb);
|
||||
// TODO: there's now two calls to this, because body.Draw() method calls this too -> is this an issue?
|
||||
body.UpdateDrawPosition();
|
||||
|
||||
if (!hideLimb)
|
||||
@@ -418,44 +478,68 @@ namespace Barotrauma
|
||||
{
|
||||
DeformSprite.Reset();
|
||||
}
|
||||
body.Draw(DeformSprite, cam, Vector2.One * Scale * TextureScale, color);
|
||||
body.Draw(DeformSprite, cam, Vector2.One * Scale * TextureScale, color, Params.MirrorHorizontally);
|
||||
}
|
||||
else
|
||||
{
|
||||
body.Draw(spriteBatch, activeSprite, color, null, Scale * TextureScale);
|
||||
body.Draw(spriteBatch, activeSprite, color, null, Scale * TextureScale, Params.MirrorHorizontally, Params.MirrorVertically);
|
||||
}
|
||||
}
|
||||
|
||||
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
|
||||
if (LightSource != null)
|
||||
{
|
||||
LightSource.Position = body.DrawPosition;
|
||||
LightSource.LightSpriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipVertically;
|
||||
}
|
||||
if (damageOverlayStrength > 0.0f && DamagedSprite != null && !hideLimb)
|
||||
{
|
||||
DamagedSprite.Draw(spriteBatch,
|
||||
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
||||
color * Math.Min(damageOverlayStrength, 1.0f), ActiveSprite.Origin,
|
||||
-body.DrawRotation,
|
||||
Scale, spriteEffect, ActiveSprite.Depth - 0.0000015f);
|
||||
}
|
||||
foreach (var decorativeSprite in DecorativeSprites)
|
||||
{
|
||||
if (!spriteAnimState[decorativeSprite].IsActive) { continue; }
|
||||
float rotation = decorativeSprite.GetRotation(ref spriteAnimState[decorativeSprite].RotationState);
|
||||
Vector2 offset = decorativeSprite.GetOffset(ref spriteAnimState[decorativeSprite].OffsetState) * Scale;
|
||||
var ca = (float)Math.Cos(-body.Rotation);
|
||||
var sa = (float)Math.Sin(-body.Rotation);
|
||||
Vector2 transformedOffset = new Vector2(ca * offset.X + sa * offset.Y, -sa * offset.X + ca * offset.Y);
|
||||
decorativeSprite.Sprite.Draw(spriteBatch, new Vector2(body.DrawPosition.X + transformedOffset.X, -(body.DrawPosition.Y + transformedOffset.Y)), color,
|
||||
-body.Rotation + rotation, Scale, spriteEffect,
|
||||
depth: decorativeSprite.Sprite.Depth);
|
||||
}
|
||||
float depthStep = 0.000001f;
|
||||
float step = depthStep;
|
||||
WearableSprite onlyDrawable = wearingItems.Find(w => w.HideOtherWearables);
|
||||
SpriteEffects spriteEffect = (dir == Direction.Right) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
|
||||
if (Params.MirrorHorizontally)
|
||||
{
|
||||
spriteEffect = spriteEffect == SpriteEffects.None ? SpriteEffects.FlipHorizontally : SpriteEffects.None;
|
||||
}
|
||||
if (Params.MirrorVertically)
|
||||
{
|
||||
spriteEffect |= SpriteEffects.FlipVertically;
|
||||
}
|
||||
if (onlyDrawable == null)
|
||||
{
|
||||
if (HerpesSprite != null)
|
||||
{
|
||||
float herpesStrength = character.CharacterHealth.GetAfflictionStrength("spaceherpes");
|
||||
if (herpesStrength > 0.0f)
|
||||
{
|
||||
DrawWearable(HerpesSprite, depthStep, spriteBatch, color * Math.Min(herpesStrength / 10.0f, 1.0f), spriteEffect);
|
||||
depthStep += 0.000001f;
|
||||
}
|
||||
DrawWearable(HerpesSprite, depthStep, spriteBatch, color * Math.Min(herpesStrength / 10.0f, 1.0f), spriteEffect);
|
||||
depthStep += step;
|
||||
}
|
||||
if (HuskSprite != null && (character.SpeciesName == "Humanhusk" || (character.SpeciesName == "Human" &&
|
||||
character.CharacterHealth.GetAffliction<AfflictionHusk>("huskinfection")?.State == AfflictionHusk.InfectionState.Active)))
|
||||
if (HuskSprite != null && enableHuskSprite)
|
||||
{
|
||||
DrawWearable(HuskSprite, depthStep, spriteBatch, color, spriteEffect);
|
||||
depthStep += 0.000001f;
|
||||
depthStep += step;
|
||||
}
|
||||
foreach (WearableSprite wearable in OtherWearables)
|
||||
{
|
||||
if (wearable.Type == WearableType.Beard && enableHuskSprite && HuskSprite != null) { continue; }
|
||||
DrawWearable(wearable, depthStep, spriteBatch, color, spriteEffect);
|
||||
//if there are multiple sprites on this limb, make the successive ones be drawn in front
|
||||
depthStep += 0.000001f;
|
||||
depthStep += step;
|
||||
}
|
||||
}
|
||||
foreach (WearableSprite wearable in WearingItems)
|
||||
@@ -463,18 +547,7 @@ namespace Barotrauma
|
||||
if (onlyDrawable != null && onlyDrawable != wearable) continue;
|
||||
DrawWearable(wearable, depthStep, spriteBatch, color, spriteEffect);
|
||||
//if there are multiple sprites on this limb, make the successive ones be drawn in front
|
||||
depthStep += 0.000001f;
|
||||
}
|
||||
|
||||
if (damageOverlayStrength > 0.0f && DamagedSprite != null && !hideLimb)
|
||||
{
|
||||
float depth = ActiveSprite.Depth - 0.0000015f;
|
||||
|
||||
DamagedSprite.Draw(spriteBatch,
|
||||
new Vector2(body.DrawPosition.X, -body.DrawPosition.Y),
|
||||
color * Math.Min(damageOverlayStrength, 1.0f), ActiveSprite.Origin,
|
||||
-body.DrawRotation,
|
||||
1.0f, spriteEffect, depth);
|
||||
depthStep += step;
|
||||
}
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
@@ -492,7 +565,7 @@ namespace Barotrauma
|
||||
from.Y = -from.Y;
|
||||
Vector2 to = ConvertUnits.ToDisplayUnits(attachJoint.WorldAnchorB);
|
||||
to.Y = -to.Y;
|
||||
var localFront = body.GetLocalFront(MathHelper.ToRadians(limbParams.Ragdoll.SpritesheetOrientation));
|
||||
var localFront = body.GetLocalFront(Params.GetSpriteOrientation());
|
||||
var front = ConvertUnits.ToDisplayUnits(body.FarseerBody.GetWorldPoint(localFront));
|
||||
front.Y = -front.Y;
|
||||
GUI.DrawLine(spriteBatch, bodyDrawPos, front, Color.Yellow, width: 2);
|
||||
@@ -503,25 +576,89 @@ namespace Barotrauma
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)to.X, (int)to.Y, 10, 10), Color.Red, true);
|
||||
GUI.DrawRectangle(spriteBatch, new Rectangle((int)front.X, (int)front.Y, 10, 10), Color.Yellow, true);
|
||||
|
||||
//Vector2 mainLimbFront = ConvertUnits.ToDisplayUnits(ragdoll.MainLimb.body.FarseerBody.GetWorldPoint(ragdoll.MainLimb.body.GetFrontLocal(MathHelper.ToRadians(ragdoll.RagdollParams.SpritesheetOrientation))));
|
||||
//Vector2 mainLimbFront = ConvertUnits.ToDisplayUnits(ragdoll.MainLimb.body.FarseerBody.GetWorldPoint(ragdoll.MainLimb.body.GetFrontLocal(MathHelper.ToRadians(limbParams.Orientation))));
|
||||
//mainLimbFront.Y = -mainLimbFront.Y;
|
||||
//var mainLimbDrawPos = ragdoll.MainLimb.body.DrawPosition;
|
||||
//mainLimbDrawPos.Y = -mainLimbDrawPos.Y;
|
||||
//GUI.DrawLine(spriteBatch, mainLimbDrawPos, mainLimbFront, Color.White, width: 5);
|
||||
//GUI.DrawRectangle(spriteBatch, new Rectangle((int)mainLimbFront.X, (int)mainLimbFront.Y, 10, 10), Color.Yellow, true);
|
||||
}
|
||||
foreach (var modifier in damageModifiers)
|
||||
DrawDamageModifiers(spriteBatch, cam, bodyDrawPos, isScreenSpace: false);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSpriteStates(float deltaTime)
|
||||
{
|
||||
foreach (int spriteGroup in DecorativeSpriteGroups.Keys)
|
||||
{
|
||||
for (int i = 0; i < DecorativeSpriteGroups[spriteGroup].Count; i++)
|
||||
{
|
||||
float rotation = -body.TransformedRotation + GetArmorSectorRotationOffset(modifier.ArmorSector) * Dir;
|
||||
Vector2 forward = VectorExtensions.Forward(rotation);
|
||||
float size = ConvertUnits.ToDisplayUnits(body.GetSize().Length() / 2);
|
||||
color = modifier.DamageMultiplier > 1 ? Color.Red : Color.GreenYellow;
|
||||
GUI.DrawLine(spriteBatch, bodyDrawPos, bodyDrawPos + Vector2.Normalize(forward) * size, color, width: (int)Math.Round(4 / cam.Zoom));
|
||||
ShapeExtensions.DrawSector(spriteBatch, bodyDrawPos, size, GetArmorSectorSize(modifier.ArmorSector) * Dir, 40, color, rotation + MathHelper.Pi, thickness: 2 / cam.Zoom);
|
||||
var decorativeSprite = DecorativeSpriteGroups[spriteGroup][i];
|
||||
if (decorativeSprite == null) { continue; }
|
||||
if (spriteGroup > 0)
|
||||
{
|
||||
// TODO
|
||||
//int activeSpriteIndex = ID % DecorativeSpriteGroups[spriteGroup].Count;
|
||||
//if (i != activeSpriteIndex)
|
||||
//{
|
||||
// spriteAnimState[decorativeSprite].IsActive = false;
|
||||
// continue;
|
||||
//}
|
||||
}
|
||||
|
||||
//check if the sprite is active (whether it should be drawn or not)
|
||||
var spriteState = spriteAnimState[decorativeSprite];
|
||||
spriteState.IsActive = true;
|
||||
foreach (PropertyConditional conditional in decorativeSprite.IsActiveConditionals)
|
||||
{
|
||||
if (!conditional.Matches(this))
|
||||
{
|
||||
spriteState.IsActive = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!spriteState.IsActive) { continue; }
|
||||
|
||||
//check if the sprite should be animated
|
||||
bool animate = true;
|
||||
foreach (PropertyConditional conditional in decorativeSprite.AnimationConditionals)
|
||||
{
|
||||
if (!conditional.Matches(this)) { animate = false; break; }
|
||||
}
|
||||
if (!animate) { continue; }
|
||||
spriteState.OffsetState += deltaTime;
|
||||
spriteState.RotationState += deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawDamageModifiers(SpriteBatch spriteBatch, Camera cam, Vector2 startPos, bool isScreenSpace)
|
||||
{
|
||||
foreach (var modifier in damageModifiers)
|
||||
{
|
||||
float rotation = -body.TransformedRotation + GetArmorSectorRotationOffset(modifier.ArmorSectorInRadians) * Dir;
|
||||
Vector2 forward = VectorExtensions.Forward(rotation);
|
||||
float size = ConvertUnits.ToDisplayUnits(body.GetSize().Length() / 2);
|
||||
if (isScreenSpace)
|
||||
{
|
||||
size *= cam.Zoom;
|
||||
}
|
||||
Color color = modifier.DamageMultiplier > 1 ? Color.Red : Color.GreenYellow;
|
||||
int width = 4;
|
||||
if (!isScreenSpace)
|
||||
{
|
||||
width = (int)Math.Round(width / cam.Zoom);
|
||||
}
|
||||
GUI.DrawLine(spriteBatch, startPos, startPos + Vector2.Normalize(forward) * size, color, width: width);
|
||||
int thickness = 2;
|
||||
if (!isScreenSpace)
|
||||
{
|
||||
thickness = (int)Math.Round(thickness / cam.Zoom);
|
||||
}
|
||||
ShapeExtensions.DrawSector(spriteBatch, startPos, size, GetArmorSectorSize(modifier.ArmorSectorInRadians) * Dir, 40, color, rotation + MathHelper.Pi, thickness);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawWearable(WearableSprite wearable, float depthStep, SpriteBatch spriteBatch, Color color, SpriteEffects spriteEffect)
|
||||
{
|
||||
if (wearable.InheritSourceRect)
|
||||
@@ -584,6 +721,26 @@ namespace Barotrauma
|
||||
Scale * textureScale, spriteEffect, depth);
|
||||
}
|
||||
|
||||
private WearableSprite GetWearableSprite(WearableType type, bool random = false)
|
||||
{
|
||||
var info = character.Info;
|
||||
if (info == null) { return null; }
|
||||
XElement element;
|
||||
if (random)
|
||||
{
|
||||
element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), type)?.FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), type)?.GetRandom(Rand.RandSync.ClientOnly);
|
||||
}
|
||||
if (element != null)
|
||||
{
|
||||
return new WearableSprite(element.Element("sprite"), type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
partial void RemoveProjSpecific()
|
||||
{
|
||||
Sprite?.Remove();
|
||||
@@ -595,6 +752,9 @@ namespace Barotrauma
|
||||
DeformSprite?.Sprite?.Remove();
|
||||
DeformSprite = null;
|
||||
|
||||
DecorativeSprites.ForEach(s => s.Remove());
|
||||
ConditionalSprites.Clear();
|
||||
|
||||
ConditionalSprites.ForEach(s => s.Remove());
|
||||
ConditionalSprites.Clear();
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace Barotrauma
|
||||
|
||||
private static bool isOpen;
|
||||
public static bool IsOpen => isOpen;
|
||||
public static bool Paused = false;
|
||||
|
||||
private static GUITextBlock activeQuestionText;
|
||||
|
||||
@@ -773,9 +774,15 @@ namespace Barotrauma
|
||||
}
|
||||
}, isCheat: true));
|
||||
|
||||
commands.Add(new Command("messagebox", "", (string[] args) =>
|
||||
commands.Add(new Command("messagebox|guimessagebox", "messagebox [header] [msg] [default/ingame]: Creates a message box.", (string[] args) =>
|
||||
{
|
||||
new GUIMessageBox("", string.Join(" ", args));
|
||||
var msgBox = new GUIMessageBox(
|
||||
args.Length > 0 ? args[0] : "",
|
||||
args.Length > 1 ? args[1] : "",
|
||||
buttons: new string[] { "OK" },
|
||||
type: args.Length < 3 || args[2] == "default" ? GUIMessageBox.Type.Default : GUIMessageBox.Type.InGame);
|
||||
|
||||
msgBox.Buttons[0].OnClicked = msgBox.Close;
|
||||
}));
|
||||
|
||||
AssignOnExecute("debugdraw", (string[] args) =>
|
||||
@@ -1121,7 +1128,7 @@ namespace Barotrauma
|
||||
{
|
||||
string filePath = args.Length > 0 ? args[0] : "Content/Texts/EnglishVanilla.xml";
|
||||
var doc = XMLExtensions.TryLoadXml(filePath);
|
||||
if (doc?.Root == null) return;
|
||||
if (doc == null) { return; }
|
||||
List<string> lines = new List<string>();
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
@@ -1154,6 +1161,7 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
var doc = XMLExtensions.TryLoadXml(destinationPath);
|
||||
if (doc == null) { return; }
|
||||
int i = 0;
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
@@ -1186,6 +1194,8 @@ namespace Barotrauma
|
||||
var sourceDoc = XMLExtensions.TryLoadXml(sourcePath);
|
||||
var destinationDoc = XMLExtensions.TryLoadXml(destinationPath);
|
||||
|
||||
if (sourceDoc == null || destinationDoc == null) { return; }
|
||||
|
||||
XElement destinationElement = destinationDoc.Root.Elements().First();
|
||||
foreach (XElement element in sourceDoc.Root.Elements())
|
||||
{
|
||||
@@ -1221,6 +1231,76 @@ namespace Barotrauma
|
||||
}
|
||||
File.WriteAllLines(filePath, lines);
|
||||
}));
|
||||
|
||||
|
||||
commands.Add(new Command("itemcomponentdocumentation", "", (string[] args) =>
|
||||
{
|
||||
Dictionary<string, string> typeNames = new Dictionary<string, string>
|
||||
{
|
||||
{ "Single", "float"},
|
||||
{ "Int32", "integer"},
|
||||
{ "Boolean", "true/false"},
|
||||
{ "String", "text"},
|
||||
};
|
||||
|
||||
var itemComponentTypes = typeof(ItemComponent).Assembly.GetTypes().Where(type => type.IsSubclassOf(typeof(ItemComponent)));
|
||||
string filePath = args.Length > 0 ? args[0] : "ItemComponentDocumentation.txt";
|
||||
List<string> lines = new List<string>();
|
||||
foreach (Type t in itemComponentTypes)
|
||||
{
|
||||
lines.Add($"[b]{t.Name}[/b]");
|
||||
lines.Add("");
|
||||
|
||||
var properties = t.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);//.Cast<System.ComponentModel.PropertyDescriptor>();
|
||||
Dictionary<string, SerializableProperty> dictionary = new Dictionary<string, SerializableProperty>();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
object[] attributes = property.GetCustomAttributes(true);
|
||||
Serialize serialize = attributes.FirstOrDefault(a => a is Serialize) as Serialize;
|
||||
if (serialize == null) { continue; }
|
||||
|
||||
string propertyTypeName = property.PropertyType.Name;
|
||||
if (typeNames.ContainsKey(propertyTypeName))
|
||||
{
|
||||
propertyTypeName = typeNames[propertyTypeName];
|
||||
}
|
||||
else if (property.PropertyType.IsEnum)
|
||||
{
|
||||
List<string> valueNames = new List<string>();
|
||||
foreach (object enumValue in Enum.GetValues(property.PropertyType))
|
||||
{
|
||||
valueNames.Add(enumValue.ToString());
|
||||
}
|
||||
propertyTypeName = string.Join("/", valueNames);
|
||||
}
|
||||
|
||||
lines.Add($"{property.Name} ({propertyTypeName})");
|
||||
|
||||
if (!string.IsNullOrEmpty(serialize.Description))
|
||||
{
|
||||
lines.Add(serialize.Description);
|
||||
}
|
||||
Editable editable = attributes.FirstOrDefault(a => a is Editable) as Editable;
|
||||
if (editable != null)
|
||||
{
|
||||
if (editable.MinValueFloat > float.MinValue || editable.MaxValueFloat < float.MaxValue)
|
||||
{
|
||||
lines.Add("Range: " + editable.MinValueFloat+"-"+editable.MaxValueFloat);
|
||||
}
|
||||
else if (editable.MinValueInt > int.MinValue || editable.MaxValueInt < int.MaxValue)
|
||||
{
|
||||
lines.Add("Range: " + editable.MinValueInt + "-" + editable.MaxValueInt);
|
||||
}
|
||||
}
|
||||
|
||||
lines.Add("Default value: " + serialize.defaultValue);
|
||||
lines.Add("");
|
||||
}
|
||||
lines.Add("");
|
||||
}
|
||||
File.WriteAllLines(filePath, lines);
|
||||
System.Diagnostics.Process.Start(Path.GetFullPath(filePath));
|
||||
}));
|
||||
#if DEBUG
|
||||
commands.Add(new Command("checkduplicates", "Checks the given language for duplicate translation keys and writes to file.", (string[] args) =>
|
||||
{
|
||||
@@ -1239,12 +1319,6 @@ namespace Barotrauma
|
||||
if (args.Length == 0) return;
|
||||
LocalizationCSVtoXML.Convert(args[0]);
|
||||
}));
|
||||
|
||||
commands.Add(new Command("guimessagebox", "guimessagebox [msg] -> Creates a message box with the parameter as a message.", (string[] args) =>
|
||||
{
|
||||
if (args.Length == 0) return;
|
||||
var dialog = new GUIMessageBox("Message box", args[0]);
|
||||
}));
|
||||
#endif
|
||||
|
||||
commands.Add(new Command("cleanbuild", "", (string[] args) =>
|
||||
@@ -1257,7 +1331,7 @@ namespace Barotrauma
|
||||
|
||||
GameMain.Config.GraphicsWidth = 0;
|
||||
GameMain.Config.GraphicsHeight = 0;
|
||||
GameMain.Config.WindowMode = WindowMode.Fullscreen;
|
||||
GameMain.Config.WindowMode = WindowMode.BorderlessWindowed;
|
||||
NewMessage("Resolution set to 0 x 0 (screen resolution will be used)", Color.Green);
|
||||
NewMessage("Fullscreen enabled", Color.Green);
|
||||
|
||||
@@ -1652,7 +1726,7 @@ namespace Barotrauma
|
||||
ThrowError("Not controlling any character!");
|
||||
return;
|
||||
}
|
||||
character.AnimController.ResetRagdoll();
|
||||
character.AnimController.ResetRagdoll(forceReload: true);
|
||||
}, isCheat: true));
|
||||
|
||||
commands.Add(new Command("reloadwearables", "Reloads the sprites of all limbs and wearable sprites (clothing) of the controlled character. Provide id or name if you want to target another character.", args =>
|
||||
@@ -1762,7 +1836,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (limb.type != LimbType.Head)
|
||||
{
|
||||
limb.RecreateSprite();
|
||||
limb.RecreateSprites();
|
||||
}
|
||||
foreach (var wearable in limb.WearingItems)
|
||||
{
|
||||
@@ -1846,6 +1920,19 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.SpawnSubmarine:Error", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + '\n' + e.Message + '\n' + e.StackTrace);
|
||||
}
|
||||
}, isCheat: true));
|
||||
|
||||
commands.Add(new Command("pause", "Toggles the pause state when playing offline", (string[] args) =>
|
||||
{
|
||||
if (GameMain.NetworkMember == null)
|
||||
{
|
||||
Paused = !Paused;
|
||||
DebugConsole.NewMessage("Game paused: " + Paused);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.NewMessage("Cannot pause when a multiplayer session is active.");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private static void ReloadWearables(Character character, int variant = 0)
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class Mission
|
||||
{
|
||||
partial void ShowMessageProjSpecific(int index)
|
||||
{
|
||||
if (index >= Headers.Count && index >= Messages.Count) return;
|
||||
if (index >= Headers.Count && index >= Messages.Count) { return; }
|
||||
|
||||
string header = index < Headers.Count ? Headers[index] : "";
|
||||
string message = index < Messages.Count ? Messages[index] : "";
|
||||
|
||||
new GUIMessageBox(header, message);
|
||||
new GUIMessageBox(header, message, buttons: new string[0], type: GUIMessageBox.Type.InGame, icon: Prefab.Icon)
|
||||
{
|
||||
IconColor = Prefab.IconColor
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ namespace Barotrauma
|
||||
{
|
||||
if (mission == null) return;
|
||||
|
||||
new GUIMessageBox(mission.Name, mission.Description, new Vector2(0.25f, 0.0f), new Point(400, 200))
|
||||
new GUIMessageBox(mission.Name, mission.Description, new string[0], type: GUIMessageBox.Type.InGame, icon: mission.Prefab.Icon)
|
||||
{
|
||||
IconColor = mission.Prefab.IconColor,
|
||||
UserData = "missionstartmessage"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class MissionPrefab
|
||||
{
|
||||
public Sprite Icon
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Color IconColor
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "icon") { continue; }
|
||||
Icon = new Sprite(subElement);
|
||||
IconColor = subElement.GetAttributeColor("color", Color.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,7 +251,7 @@ namespace Barotrauma
|
||||
{
|
||||
this.texDims = texDims;
|
||||
this.baseChar = baseChar;
|
||||
face.SetPixelSizes(0, size);
|
||||
lock (mutex) { face.SetPixelSizes(0, size); }
|
||||
face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal);
|
||||
baseHeight = face.Glyph.Metrics.Height.ToInt32();
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
@@ -263,6 +263,7 @@ namespace Barotrauma
|
||||
uint glyphIndex = face.GetCharIndex(character);
|
||||
if (glyphIndex == 0) { return; }
|
||||
|
||||
lock (mutex) { face.SetPixelSizes(0, size); }
|
||||
face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
|
||||
if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Barotrauma.CharacterEditor;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Sounds;
|
||||
using Barotrauma.Tutorials;
|
||||
@@ -8,6 +9,7 @@ using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -154,19 +156,38 @@ namespace Barotrauma
|
||||
public static void Init(GameWindow window, IEnumerable<ContentPackage> selectedContentPackages, GraphicsDevice graphicsDevice)
|
||||
{
|
||||
GUI.graphicsDevice = graphicsDevice;
|
||||
var uiStyles = ContentPackage.GetFilesOfType(selectedContentPackages, ContentType.UIStyle).ToList();
|
||||
|
||||
if (uiStyles.Count == 0)
|
||||
var files = ContentPackage.GetFilesOfType(selectedContentPackages, ContentType.UIStyle);
|
||||
XElement selectedStyle = null;
|
||||
foreach (var file in files)
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(file);
|
||||
if (doc == null) { continue; }
|
||||
var mainElement = doc.Root;
|
||||
if (doc.Root.IsOverride())
|
||||
{
|
||||
mainElement = doc.Root.FirstElement();
|
||||
if (selectedStyle != null)
|
||||
{
|
||||
DebugConsole.NewMessage($"Overriding the ui styles with '{file}'", Color.Yellow);
|
||||
}
|
||||
}
|
||||
else if (selectedStyle != null)
|
||||
{
|
||||
DebugConsole.ThrowError("Another ui style already loaded! Use <override></override> tags to override it.");
|
||||
break;
|
||||
}
|
||||
selectedStyle = mainElement;
|
||||
}
|
||||
if (selectedStyle == null)
|
||||
{
|
||||
DebugConsole.ThrowError("No UI styles defined in the selected content package!");
|
||||
return;
|
||||
}
|
||||
else if (uiStyles.Count > 1)
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Multiple UI styles defined in the selected content package! Selecting the first one.");
|
||||
Style = new GUIStyle(selectedStyle, graphicsDevice);
|
||||
}
|
||||
|
||||
Style = new GUIStyle(uiStyles[0], graphicsDevice);
|
||||
if (CJKFont == null)
|
||||
{
|
||||
CJKFont = new ScalableFont("Content/Fonts/NotoSans/NotoSansCJKsc-Bold.otf",
|
||||
@@ -407,6 +428,10 @@ namespace Barotrauma
|
||||
{
|
||||
debugDrawEvents = !debugDrawEvents;
|
||||
}
|
||||
if (MouseOn != null)
|
||||
{
|
||||
DrawString(spriteBatch, new Vector2(GameMain.GraphicsWidth - 500, 20), $"Selected UI Element: {MouseOn.GetType().ToString()}", Color.LightGreen, Color.Black * 0.5f, 0, SmallFont);
|
||||
}
|
||||
}
|
||||
|
||||
if (HUDLayoutSettings.DebugDraw) HUDLayoutSettings.Draw(spriteBatch);
|
||||
@@ -601,10 +626,7 @@ namespace Barotrauma
|
||||
|
||||
private static void HandlePersistingElements(float deltaTime)
|
||||
{
|
||||
if (GUIMessageBox.VisibleBox != null && GUIMessageBox.VisibleBox.UserData as string != "verificationprompt" && GUIMessageBox.VisibleBox.UserData as string != "bugreporter")
|
||||
{
|
||||
GUIMessageBox.VisibleBox.AddToGUIUpdateList();
|
||||
}
|
||||
GUIMessageBox.AddActiveToGUIUpdateList();
|
||||
|
||||
if (pauseMenuOpen)
|
||||
{
|
||||
@@ -1570,7 +1592,7 @@ namespace Barotrauma
|
||||
button.OnClicked += (btn, userData) =>
|
||||
{
|
||||
var quitButton = button;
|
||||
if (GameMain.GameSession != null || (Screen.Selected is CharacterEditorScreen charEditScreen || Screen.Selected is SubEditorScreen subEditScreen))
|
||||
if (GameMain.GameSession != null || (Screen.Selected is CharacterEditorScreen || Screen.Selected is SubEditorScreen))
|
||||
{
|
||||
string text = GameMain.GameSession == null ? "PauseMenuQuitVerificationEditor" : "PauseMenuQuitVerification";
|
||||
var msgBox = new GUIMessageBox("", TextManager.Get(text), new string[] { TextManager.Get("Yes"), TextManager.Get("Cancel") })
|
||||
|
||||
@@ -163,6 +163,12 @@ namespace Barotrauma
|
||||
{
|
||||
TextColor = this.style == null ? Color.Black : this.style.textColor
|
||||
};
|
||||
if (rectT.Rect.Height == 0 && !string.IsNullOrEmpty(text))
|
||||
{
|
||||
RectTransform.Resize(new Point(RectTransform.Rect.Width, (int)Font.MeasureString(textBlock.Text).Y));
|
||||
RectTransform.MinSize = textBlock.RectTransform.MinSize = new Point(0, Rect.Height);
|
||||
TextBlock.SetTextPos();
|
||||
}
|
||||
GUI.Style.Apply(textBlock, "", this);
|
||||
Enabled = true;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using System;
|
||||
using System.Xml.Linq;
|
||||
using System.IO;
|
||||
using RestSharp;
|
||||
using System.Net;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -596,5 +600,340 @@ namespace Barotrauma
|
||||
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
public static GUIComponent FromXML(XElement element, RectTransform parent)
|
||||
{
|
||||
GUIComponent component = null;
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() == "conditional" &&
|
||||
!CheckConditional(subElement))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
switch (element.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "text":
|
||||
case "guitextblock":
|
||||
component = LoadGUITextBlock(element, parent);
|
||||
break;
|
||||
case "link":
|
||||
component = LoadLink(element, parent);
|
||||
break;
|
||||
case "frame":
|
||||
case "guiframe":
|
||||
case "spacing":
|
||||
component = LoadGUIFrame(element, parent);
|
||||
break;
|
||||
case "button":
|
||||
case "guibutton":
|
||||
component = LoadGUIButton(element, parent);
|
||||
break;
|
||||
case "listbox":
|
||||
case "guilistbox":
|
||||
component = LoadGUIListBox(element, parent);
|
||||
break;
|
||||
case "guilayoutgroup":
|
||||
case "layoutgroup":
|
||||
component = LoadGUILayoutGroup(element, parent);
|
||||
break;
|
||||
case "image":
|
||||
case "guiimage":
|
||||
component = LoadGUIImage(element, parent);
|
||||
break;
|
||||
case "accordion":
|
||||
return LoadAccordion(element, parent);
|
||||
case "gridtext":
|
||||
LoadGridText(element, parent);
|
||||
return null;
|
||||
default:
|
||||
throw new NotImplementedException("Loading GUI component \""+element.Name+"\" from XML is not implemented.");
|
||||
}
|
||||
|
||||
if (component != null)
|
||||
{
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() == "conditional") { continue; }
|
||||
FromXML(subElement, component is GUIListBox listBox ? listBox.Content.RectTransform : component.RectTransform);
|
||||
}
|
||||
|
||||
if (element.GetAttributeBool("resizetofitchildren", false))
|
||||
{
|
||||
Vector2 relativeResizeScale = element.GetAttributeVector2("relativeresizescale", Vector2.One);
|
||||
if (component is GUILayoutGroup layoutGroup)
|
||||
{
|
||||
layoutGroup.RectTransform.NonScaledSize =
|
||||
layoutGroup.IsHorizontal ?
|
||||
new Point(layoutGroup.Children.Sum(c => c.Rect.Width), layoutGroup.Rect.Height) :
|
||||
component.RectTransform.MinSize = new Point(layoutGroup.Rect.Width, layoutGroup.Children.Sum(c => c.Rect.Height));
|
||||
if (layoutGroup.CountChildren > 0)
|
||||
{
|
||||
layoutGroup.RectTransform.NonScaledSize +=
|
||||
layoutGroup.IsHorizontal ?
|
||||
new Point((int)((layoutGroup.CountChildren - 1) * (layoutGroup.AbsoluteSpacing + layoutGroup.Rect.Width * layoutGroup.RelativeSpacing)), 0) :
|
||||
new Point(0, (int)((layoutGroup.CountChildren - 1) * (layoutGroup.AbsoluteSpacing + layoutGroup.Rect.Height * layoutGroup.RelativeSpacing)));
|
||||
}
|
||||
}
|
||||
else if (component is GUIListBox listBox)
|
||||
{
|
||||
listBox.RectTransform.NonScaledSize =
|
||||
listBox.ScrollBar.IsHorizontal ?
|
||||
new Point(listBox.Children.Sum(c => c.Rect.Width + listBox.Spacing), listBox.Rect.Height) :
|
||||
component.RectTransform.MinSize = new Point(listBox.Rect.Width, listBox.Children.Sum(c => c.Rect.Height + listBox.Spacing));
|
||||
}
|
||||
else
|
||||
{
|
||||
component.RectTransform.NonScaledSize =
|
||||
new Point(
|
||||
component.Children.Max(c => c.Rect.Right) - component.Children.Min(c => c.Rect.X),
|
||||
component.Children.Max(c => c.Rect.Bottom) - component.Children.Min(c => c.Rect.Y));
|
||||
}
|
||||
component.RectTransform.NonScaledSize =
|
||||
component.RectTransform.NonScaledSize.Multiply(relativeResizeScale);
|
||||
}
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
private static bool CheckConditional(XElement element)
|
||||
{
|
||||
foreach (XAttribute attribute in element.Attributes())
|
||||
{
|
||||
switch (attribute.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "language":
|
||||
string[] languages = element.GetAttributeStringArray(attribute.Name.ToString(), new string[0]);
|
||||
if (!languages.Any(l => GameMain.Config.Language.ToLower() == l.ToLower())) { return false; }
|
||||
break;
|
||||
case "gameversion":
|
||||
var version = new Version(attribute.Value);
|
||||
if (GameMain.Version != version) { return false; }
|
||||
break;
|
||||
case "mingameversion":
|
||||
var minVersion = new Version(attribute.Value);
|
||||
if (GameMain.Version < minVersion) { return false; }
|
||||
break;
|
||||
case "maxgameversion":
|
||||
var maxVersion = new Version(attribute.Value);
|
||||
if (GameMain.Version > maxVersion) { return false; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static GUITextBlock LoadGUITextBlock(XElement element, RectTransform parent, string overrideText = null, Anchor? anchor = null)
|
||||
{
|
||||
string text = element.Attribute("text") == null ?
|
||||
element.ElementInnerText() :
|
||||
element.GetAttributeString("text", "");
|
||||
text = text.Replace(@"\n", "\n");
|
||||
|
||||
string style = element.GetAttributeString("style", "");
|
||||
if (style == "null") { style = null; }
|
||||
Color? color = null;
|
||||
if (element.Attribute("color") != null) { color = element.GetAttributeColor("color", Color.White); }
|
||||
float scale = element.GetAttributeFloat("scale", 1.0f);
|
||||
bool wrap = element.GetAttributeBool("wrap", true);
|
||||
Alignment alignment = Alignment.Center;
|
||||
Enum.TryParse(element.GetAttributeString("alignment", "Center"), out alignment);
|
||||
ScalableFont font = GUI.Font;
|
||||
switch (element.GetAttributeString("font", "Font").ToLowerInvariant())
|
||||
{
|
||||
case "font":
|
||||
font = GUI.Font;
|
||||
break;
|
||||
case "smallfont":
|
||||
font = GUI.SmallFont;
|
||||
break;
|
||||
case "largefont":
|
||||
font = GUI.LargeFont;
|
||||
break;
|
||||
case "videotitlefont":
|
||||
font = GUI.VideoTitleFont;
|
||||
break;
|
||||
case "objectivetitlefont":
|
||||
font = GUI.ObjectiveTitleFont;
|
||||
break;
|
||||
case "objectivenamefont":
|
||||
font = GUI.ObjectiveNameFont;
|
||||
break;
|
||||
}
|
||||
|
||||
var textBlock = new GUITextBlock(RectTransform.Load(element, parent),
|
||||
text, color, font, alignment, wrap: wrap, style: style)
|
||||
{
|
||||
TextScale = scale
|
||||
};
|
||||
if (anchor.HasValue) { textBlock.RectTransform.SetPosition(anchor.Value); }
|
||||
textBlock.RectTransform.IsFixedSize = true;
|
||||
textBlock.RectTransform.NonScaledSize = new Point(textBlock.Rect.Width, textBlock.Rect.Height);
|
||||
return textBlock;
|
||||
}
|
||||
|
||||
private static GUIButton LoadLink(XElement element, RectTransform parent)
|
||||
{
|
||||
var button = LoadGUIButton(element, parent);
|
||||
string url = element.GetAttributeString("url", "");
|
||||
button.OnClicked = (btn, userdata) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Diagnostics.Process.Start(url);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to open url \""+url+"\".", e);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return button;
|
||||
}
|
||||
|
||||
private static void LoadGridText(XElement element, RectTransform parent)
|
||||
{
|
||||
string text = element.Attribute("text") == null ?
|
||||
element.ElementInnerText() :
|
||||
element.GetAttributeString("text", "");
|
||||
text = text.Replace(@"\n", "\n");
|
||||
|
||||
string[] elements = text.Split(',');
|
||||
RectTransform lineContainer = null;
|
||||
for (int i = 0; i < elements.Length; i++)
|
||||
{
|
||||
switch (i % 3)
|
||||
{
|
||||
case 0:
|
||||
lineContainer = LoadGUITextBlock(element, parent, elements[i], Anchor.CenterLeft).RectTransform;
|
||||
lineContainer.Anchor = Anchor.TopCenter;
|
||||
lineContainer.Pivot = Pivot.TopCenter;
|
||||
lineContainer.NonScaledSize = new Point((int)(parent.NonScaledSize.X * 0.7f), lineContainer.NonScaledSize.Y);
|
||||
break;
|
||||
case 1:
|
||||
LoadGUITextBlock(element, lineContainer, elements[i], Anchor.Center).TextAlignment = Alignment.Center;
|
||||
break;
|
||||
case 2:
|
||||
LoadGUITextBlock(element, lineContainer, elements[i], Anchor.CenterRight).TextAlignment = Alignment.CenterRight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static GUIFrame LoadGUIFrame(XElement element, RectTransform parent)
|
||||
{
|
||||
string style = element.GetAttributeString("style", element.Name.ToString().ToLowerInvariant() == "spacing" ? null : "");
|
||||
if (style == "null") { style = null; }
|
||||
return new GUIFrame(RectTransform.Load(element, parent), style: style);
|
||||
}
|
||||
|
||||
private static GUIButton LoadGUIButton(XElement element, RectTransform parent)
|
||||
{
|
||||
string style = element.GetAttributeString("style", "");
|
||||
if (style == "null") { style = null; }
|
||||
|
||||
Alignment textAlignment = Alignment.Center;
|
||||
Enum.TryParse(element.GetAttributeString("textalignment", "Center"), out textAlignment);
|
||||
|
||||
string text = element.Attribute("text") == null ?
|
||||
element.ElementInnerText() :
|
||||
element.GetAttributeString("text", "");
|
||||
text = text.Replace(@"\n", "\n");
|
||||
|
||||
return new GUIButton(RectTransform.Load(element, parent),
|
||||
text: text,
|
||||
textAlignment: textAlignment,
|
||||
style: style);
|
||||
}
|
||||
|
||||
private static GUIListBox LoadGUIListBox(XElement element, RectTransform parent)
|
||||
{
|
||||
string style = element.GetAttributeString("style", "");
|
||||
if (style == "null") { style = null; }
|
||||
bool isHorizontal = element.GetAttributeBool("ishorizontal", !element.GetAttributeBool("isvertical", true));
|
||||
return new GUIListBox(RectTransform.Load(element, parent), isHorizontal, style: style);
|
||||
}
|
||||
|
||||
private static GUILayoutGroup LoadGUILayoutGroup(XElement element, RectTransform parent)
|
||||
{
|
||||
bool isHorizontal = element.GetAttributeBool("ishorizontal", !element.GetAttributeBool("isvertical", true));
|
||||
|
||||
Enum.TryParse(element.GetAttributeString("childanchor", "TopLeft"), out Anchor childAnchor);
|
||||
return new GUILayoutGroup(RectTransform.Load(element, parent), isHorizontal, childAnchor)
|
||||
{
|
||||
Stretch = element.GetAttributeBool("stretch", false),
|
||||
RelativeSpacing = element.GetAttributeFloat("relativespacing", 0.0f),
|
||||
AbsoluteSpacing = element.GetAttributeInt("absolutespacing", 0),
|
||||
};
|
||||
}
|
||||
|
||||
private static GUIImage LoadGUIImage(XElement element, RectTransform parent)
|
||||
{
|
||||
Sprite sprite = null;
|
||||
|
||||
string url = element.GetAttributeString("url", "");
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
string localFileName = Path.GetFileNameWithoutExtension(url.Replace("/", "").Replace(":", "").Replace("https", "").Replace("http", ""))
|
||||
.Replace(".", "");
|
||||
localFileName += Path.GetExtension(url);
|
||||
string localFilePath = Path.Combine("Downloads", localFileName);
|
||||
if (!File.Exists(localFilePath))
|
||||
{
|
||||
Uri baseAddress = new Uri(url);
|
||||
Uri remoteDirectory = new Uri(baseAddress, ".");
|
||||
string remoteFileName = Path.GetFileName(baseAddress.LocalPath);
|
||||
IRestClient client = new RestClient(remoteDirectory);
|
||||
var response = client.Execute(new RestRequest(remoteFileName, Method.GET));
|
||||
if (response.ResponseStatus != ResponseStatus.Completed) { return null; }
|
||||
if (response.StatusCode != HttpStatusCode.OK) { return null; }
|
||||
|
||||
if (!Directory.Exists("Downloads")) { Directory.CreateDirectory("Downloads"); }
|
||||
File.WriteAllBytes(localFilePath, response.RawBytes);
|
||||
}
|
||||
sprite = new Sprite(element, "Downloads", localFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite = new Sprite(element);
|
||||
}
|
||||
|
||||
return new GUIImage(RectTransform.Load(element, parent), sprite, scaleToFit: true);
|
||||
}
|
||||
|
||||
private static GUIButton LoadAccordion(XElement element, RectTransform parent)
|
||||
{
|
||||
var button = LoadGUIButton(element, parent);
|
||||
List<GUIComponent> content = new List<GUIComponent>();
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
var contentElement = FromXML(subElement, parent);
|
||||
if (contentElement != null)
|
||||
{
|
||||
contentElement.Visible = false;
|
||||
contentElement.IgnoreLayoutGroups = true;
|
||||
content.Add(contentElement);
|
||||
}
|
||||
}
|
||||
button.OnClicked = (btn, userdata) =>
|
||||
{
|
||||
bool visible = content.FirstOrDefault()?.Visible ?? true;
|
||||
foreach (GUIComponent contentElement in content)
|
||||
{
|
||||
contentElement.Visible = !visible;
|
||||
contentElement.IgnoreLayoutGroups = !contentElement.Visible;
|
||||
}
|
||||
if (button.Parent is GUILayoutGroup layoutGroup)
|
||||
{
|
||||
layoutGroup.Recalculate();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return button;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,12 @@ namespace Barotrauma
|
||||
get { return Math.Max(400, 400 * (GameMain.GraphicsWidth / 1920)); }
|
||||
}
|
||||
|
||||
public enum Type
|
||||
{
|
||||
Default,
|
||||
InGame
|
||||
}
|
||||
|
||||
public List<GUIButton> Buttons { get; private set; } = new List<GUIButton>();
|
||||
//public GUIFrame BackgroundFrame { get; private set; }
|
||||
public GUILayoutGroup Content { get; private set; }
|
||||
@@ -22,6 +28,29 @@ namespace Barotrauma
|
||||
public GUITextBlock Text { get; private set; }
|
||||
public string Tag { get; private set; }
|
||||
|
||||
public GUIImage Icon
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Color IconColor
|
||||
{
|
||||
get { return Icon == null ? Color.White : Icon.Color; }
|
||||
set
|
||||
{
|
||||
if (Icon == null) { return; }
|
||||
Icon.Color = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool alwaysVisible;
|
||||
|
||||
private float openState;
|
||||
private bool closing;
|
||||
|
||||
private Type type;
|
||||
|
||||
public static GUIComponent VisibleBox => MessageBoxes.LastOrDefault();
|
||||
|
||||
public GUIMessageBox(string headerText, string text, Vector2? relativeSize = null, Point? minSize = null)
|
||||
@@ -29,12 +58,11 @@ namespace Barotrauma
|
||||
{
|
||||
this.Buttons[0].OnClicked = Close;
|
||||
}
|
||||
|
||||
public GUIMessageBox(string headerText, string text, string[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, string tag = "")
|
||||
: base(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: "")
|
||||
|
||||
public GUIMessageBox(string headerText, string text, string[] buttons, Vector2? relativeSize = null, Point? minSize = null, Alignment textAlignment = Alignment.TopLeft, Type type = Type.Default, string tag = "", Sprite icon = null)
|
||||
: base(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: GUI.Style.GetComponentStyle("GUIMessageBox." + type) != null ? "GUIMessageBox." + type : "GUIMessageBox")
|
||||
{
|
||||
//int width = (int)(DefaultWidth * GUI.Scale), height = 0;
|
||||
int width = DefaultWidth, height = 0;
|
||||
int width = (int)(DefaultWidth * (type == Type.Default ? 1.0f : 1.5f)), height = 0;
|
||||
if (relativeSize.HasValue)
|
||||
{
|
||||
width = (int)(GameMain.GraphicsWidth * relativeSize.Value.X);
|
||||
@@ -49,137 +77,198 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, Anchor.Center) { IsFixedSize = false }, style: null);
|
||||
InnerFrame = new GUIFrame(new RectTransform(new Point(width, height), RectTransform, type == Type.InGame ? Anchor.TopCenter : Anchor.Center) { IsFixedSize = false }, style: null);
|
||||
GUI.Style.Apply(InnerFrame, "", this);
|
||||
|
||||
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
|
||||
this.type = type;
|
||||
Tag = tag;
|
||||
|
||||
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform),
|
||||
headerText, textAlignment: Alignment.Center, wrap: true);
|
||||
GUI.Style.Apply(Header, "", this);
|
||||
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
if (type == Type.Default)
|
||||
{
|
||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform),
|
||||
text, textAlignment: textAlignment, wrap: true);
|
||||
GUI.Style.Apply(Text, "", this);
|
||||
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||
new Point(Text.Rect.Width, Text.Rect.Height);
|
||||
Text.RectTransform.IsFixedSize = true;
|
||||
}
|
||||
Content = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.85f), InnerFrame.RectTransform, Anchor.Center)) { AbsoluteSpacing = 5 };
|
||||
|
||||
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform),
|
||||
headerText, textAlignment: Alignment.Center, wrap: true);
|
||||
GUI.Style.Apply(Header, "", this);
|
||||
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
||||
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), Content.RectTransform, Anchor.BottomCenter, maxSize: new Point(1000, 50)),
|
||||
isHorizontal: true, childAnchor: buttons.Length > 1 ? Anchor.BottomLeft : Anchor.Center)
|
||||
{
|
||||
AbsoluteSpacing = 5,
|
||||
IgnoreLayoutGroups = true
|
||||
};
|
||||
buttonContainer.RectTransform.NonScaledSize = buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.MaxSize =
|
||||
new Point(buttonContainer.Rect.Width, (int)(30 * GUI.Scale));
|
||||
buttonContainer.RectTransform.IsFixedSize = true;
|
||||
|
||||
if (height == 0)
|
||||
{
|
||||
height += Header.Rect.Height + Content.AbsoluteSpacing;
|
||||
height += (Text == null ? 0 : Text.Rect.Height) + Content.AbsoluteSpacing;
|
||||
height += buttonContainer.Rect.Height;
|
||||
if (minSize.HasValue)
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
height = Math.Max(height, minSize.Value.Y);
|
||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
|
||||
GUI.Style.Apply(Text, "", this);
|
||||
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||
new Point(Text.Rect.Width, Text.Rect.Height);
|
||||
Text.RectTransform.IsFixedSize = true;
|
||||
}
|
||||
|
||||
InnerFrame.RectTransform.NonScaledSize =
|
||||
new Point(InnerFrame.Rect.Width, (int)Math.Max(height / Content.RectTransform.RelativeSize.Y, height + (int)(50 * GUI.yScale)));
|
||||
Content.RectTransform.NonScaledSize =
|
||||
new Point(Content.Rect.Width, height);
|
||||
}
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), Content.RectTransform, Anchor.BottomCenter, maxSize: new Point(1000, 50)),
|
||||
isHorizontal: true, childAnchor: buttons.Length > 1 ? Anchor.BottomLeft : Anchor.Center)
|
||||
{
|
||||
AbsoluteSpacing = 5,
|
||||
IgnoreLayoutGroups = true
|
||||
};
|
||||
buttonContainer.RectTransform.NonScaledSize = buttonContainer.RectTransform.MinSize = buttonContainer.RectTransform.MaxSize =
|
||||
new Point(buttonContainer.Rect.Width, (int)(30 * GUI.Scale));
|
||||
buttonContainer.RectTransform.IsFixedSize = true;
|
||||
|
||||
Buttons = new List<GUIButton>(buttons.Length);
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
if (height == 0)
|
||||
{
|
||||
height += Header.Rect.Height + Content.AbsoluteSpacing;
|
||||
height += (Text == null ? 0 : Text.Rect.Height) + Content.AbsoluteSpacing;
|
||||
height += buttonContainer.Rect.Height;
|
||||
if (minSize.HasValue) { height = Math.Max(height, minSize.Value.Y); }
|
||||
|
||||
InnerFrame.RectTransform.NonScaledSize =
|
||||
new Point(InnerFrame.Rect.Width, (int)Math.Max(height / Content.RectTransform.RelativeSize.Y, height + (int)(50 * GUI.yScale)));
|
||||
Content.RectTransform.NonScaledSize =
|
||||
new Point(Content.Rect.Width, height);
|
||||
}
|
||||
|
||||
Buttons = new List<GUIButton>(buttons.Length);
|
||||
for (int i = 0; i < buttons.Length; i++)
|
||||
{
|
||||
var button = new GUIButton(new RectTransform(new Vector2(Math.Min(0.9f / buttons.Length, 0.5f), 1.0f), buttonContainer.RectTransform), buttons[i], style: "GUIButtonLarge");
|
||||
Buttons.Add(button);
|
||||
}
|
||||
}
|
||||
else if (type == Type.InGame)
|
||||
{
|
||||
var button = new GUIButton(new RectTransform(new Vector2(Math.Min(0.9f / buttons.Length, 0.5f), 1.0f), buttonContainer.RectTransform), buttons[i], style: "GUIButtonLarge");
|
||||
Buttons.Add(button);
|
||||
}
|
||||
InnerFrame.RectTransform.AbsoluteOffset = new Point(0, GameMain.GraphicsHeight);
|
||||
alwaysVisible = true;
|
||||
CanBeFocused = false;
|
||||
GUI.Style.Apply(InnerFrame, "", this);
|
||||
|
||||
var horizontalLayoutGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.98f, 0.95f), InnerFrame.RectTransform, Anchor.Center),
|
||||
isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
if (icon != null)
|
||||
{
|
||||
Icon = new GUIImage(new RectTransform(new Vector2(0.2f, 0.95f), horizontalLayoutGroup.RectTransform), icon, scaleToFit: true);
|
||||
}
|
||||
|
||||
Content = new GUILayoutGroup(new RectTransform(new Vector2(icon != null ? 0.65f : 0.85f, 1.0f), horizontalLayoutGroup.RectTransform));
|
||||
|
||||
var buttonContainer = new GUIFrame(new RectTransform(new Vector2(0.15f, 1.0f), horizontalLayoutGroup.RectTransform), style: null);
|
||||
Buttons = new List<GUIButton>(1)
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(0.5f, 0.5f), buttonContainer.RectTransform, Anchor.Center),
|
||||
style: GUI.Style.GetComponentStyle("GUIButtonSolidHorizontalArrow") != null ? "GUIButtonSolidHorizontalArrow" : "GUIButtonHorizontalArrow")
|
||||
{
|
||||
OnClicked = Close
|
||||
}
|
||||
};
|
||||
|
||||
Header = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), headerText, wrap: true);
|
||||
GUI.Style.Apply(Header, "", this);
|
||||
Header.RectTransform.MinSize = new Point(0, Header.Rect.Height);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
Text = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), Content.RectTransform), text, textAlignment: textAlignment, wrap: true);
|
||||
GUI.Style.Apply(Text, "", this);
|
||||
/*Content.Recalculate();
|
||||
Text.RectTransform.NonScaledSize = Text.RectTransform.MinSize = Text.RectTransform.MaxSize =
|
||||
new Point(Text.Rect.Width, Text.Rect.Height);
|
||||
Text.RectTransform.IsFixedSize = true;*/
|
||||
}
|
||||
|
||||
if (height == 0)
|
||||
{
|
||||
height += Header.Rect.Height + Content.AbsoluteSpacing;
|
||||
height += (Text == null ? 0 : Text.Rect.Height) + Content.AbsoluteSpacing;
|
||||
if (minSize.HasValue) { height = Math.Max(height, minSize.Value.Y); }
|
||||
|
||||
InnerFrame.RectTransform.NonScaledSize =
|
||||
new Point(InnerFrame.Rect.Width, (int)Math.Max(height / Content.RectTransform.RelativeSize.Y, height + (int)(50 * GUI.yScale)));
|
||||
Content.RectTransform.NonScaledSize =
|
||||
new Point(Content.Rect.Width, height);
|
||||
}
|
||||
Buttons[0].RectTransform.MaxSize = new Point(Math.Min(Buttons[0].Rect.Width, Buttons[0].Rect.Height));
|
||||
}
|
||||
|
||||
MessageBoxes.Add(this);
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// This is the new constructor.
|
||||
///// TODO: for some reason the background does not prohibit input on the elements that are behind the box
|
||||
///// TODO: allow providing buttons in the constructor
|
||||
///// </summary>
|
||||
/*public GUIMessageBox(RectTransform rectT, string headerText, string text, Alignment textAlignment = Alignment.TopCenter)
|
||||
: base(rectT, "")
|
||||
public static void AddActiveToGUIUpdateList()
|
||||
{
|
||||
//BackgroundFrame = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), rectT, Anchor.Center), null, Color.Black * 0.5f);
|
||||
float headerHeight = 0.2f;
|
||||
float margin = 0.05f;
|
||||
InnerFrame = new GUIFrame(rectT);
|
||||
GUI.Style.Apply(InnerFrame, "", this);
|
||||
Header = null;
|
||||
if (!string.IsNullOrWhiteSpace(headerText))
|
||||
for (int i = 0; i < MessageBoxes.Count; i++)
|
||||
{
|
||||
Header = new GUITextBlock(new RectTransform(new Vector2(1, headerHeight), InnerFrame.RectTransform, Anchor.TopCenter)
|
||||
if (MessageBoxes[i] is GUIMessageBox alwaysVisibleMsgBox && alwaysVisibleMsgBox.alwaysVisible)
|
||||
{
|
||||
RelativeOffset = new Vector2(0, margin)
|
||||
}, headerText, textAlignment: Alignment.Center);
|
||||
GUI.Style.Apply(Header, "", this);
|
||||
alwaysVisibleMsgBox.AddToGUIUpdateList();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
for (int i = MessageBoxes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
float offset = headerHeight + margin;
|
||||
var size = Header == null ? Vector2.One : new Vector2(1 - margin * 2, 1 - offset + margin);
|
||||
Text = new GUITextBlock(new RectTransform(size, InnerFrame.RectTransform, Anchor.TopCenter)
|
||||
if (MessageBoxes[i].UserData as string == "verificationprompt" ||
|
||||
MessageBoxes[i].UserData as string == "bugreporter")
|
||||
{
|
||||
RelativeOffset = new Vector2(0, offset)
|
||||
}, text, textAlignment: textAlignment, wrap: true);
|
||||
GUI.Style.Apply(Text, "", this);
|
||||
continue;
|
||||
}
|
||||
if (!(MessageBoxes[i] is GUIMessageBox msgBox) || !msgBox.alwaysVisible)
|
||||
{
|
||||
MessageBoxes[i].AddToGUIUpdateList();
|
||||
break;
|
||||
}
|
||||
}
|
||||
MessageBoxes.Add(this);
|
||||
}*/
|
||||
}
|
||||
|
||||
protected override void Update(float deltaTime)
|
||||
{
|
||||
if (type == Type.InGame)
|
||||
{
|
||||
Vector2 initialPos = new Vector2(0.0f, GameMain.GraphicsHeight);
|
||||
Vector2 defaultPos = new Vector2(0.0f, HUDLayoutSettings.InventoryAreaLower.Y - InnerFrame.Rect.Height - 20 * GUI.Scale);
|
||||
Vector2 endPos = new Vector2(GameMain.GraphicsWidth, defaultPos.Y);
|
||||
|
||||
/*for (int i = MessageBoxes.IndexOf(this); i >= 0; i--)
|
||||
{
|
||||
if (MessageBoxes[i] is GUIMessageBox otherMsgBox && otherMsgBox != this && otherMsgBox.type == type && !otherMsgBox.closing)
|
||||
{
|
||||
defaultPos = new Vector2(
|
||||
Math.Max(otherMsgBox.InnerFrame.RectTransform.AbsoluteOffset.X + 10 * GUI.Scale, defaultPos.X),
|
||||
Math.Max(otherMsgBox.InnerFrame.RectTransform.AbsoluteOffset.Y + 10 * GUI.Scale, defaultPos.Y));
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!closing)
|
||||
{
|
||||
InnerFrame.RectTransform.AbsoluteOffset = Vector2.SmoothStep(initialPos, defaultPos, openState).ToPoint();
|
||||
openState = Math.Min(openState + deltaTime * 2.0f, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
openState += deltaTime * 2.0f;
|
||||
InnerFrame.RectTransform.AbsoluteOffset = Vector2.SmoothStep(defaultPos, endPos, openState - 1.0f).ToPoint();
|
||||
if (openState >= 2.0f)
|
||||
{
|
||||
if (Parent != null) { Parent.RemoveChild(this); }
|
||||
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//public override void AddToGUIUpdateList(bool ignoreChildren = false, bool updateLast = false)
|
||||
//{
|
||||
// base.AddToGUIUpdateList(ignoreChildren, updateLast);
|
||||
//}
|
||||
|
||||
//public override void Draw(SpriteBatch spriteBatch, bool drawChildren = true)
|
||||
//{
|
||||
// if (RectTransform == null)
|
||||
// {
|
||||
// base.Draw(spriteBatch, drawChildren);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // Custom draw order so that the background is rendered behind the parent.
|
||||
// if (drawChildren)
|
||||
// {
|
||||
// BackgroundFrame?.Draw(spriteBatch);
|
||||
// }
|
||||
// base.Draw(spriteBatch, false);
|
||||
// if (drawChildren)
|
||||
// {
|
||||
// InnerFrame?.Draw(spriteBatch);
|
||||
// Header?.Draw(spriteBatch);
|
||||
// Text?.Draw(spriteBatch);
|
||||
// Buttons.ForEach(b => b.Draw(spriteBatch));
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (Parent != null) Parent.RemoveChild(this);
|
||||
if (MessageBoxes.Contains(this)) MessageBoxes.Remove(this);
|
||||
if (type == Type.InGame)
|
||||
{
|
||||
closing = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Parent != null) { Parent.RemoveChild(this); }
|
||||
if (MessageBoxes.Contains(this)) { MessageBoxes.Remove(this); }
|
||||
}
|
||||
}
|
||||
|
||||
public bool Close(GUIButton button, object obj)
|
||||
{
|
||||
Close();
|
||||
|
||||
Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,27 +30,12 @@ namespace Barotrauma
|
||||
|
||||
public SpriteSheet FocusIndicator { get; private set; }
|
||||
|
||||
public GUIStyle(string file, GraphicsDevice graphicsDevice)
|
||||
public GUIStyle(XElement element, GraphicsDevice graphicsDevice)
|
||||
{
|
||||
this.graphicsDevice = graphicsDevice;
|
||||
componentStyles = new Dictionary<string, GUIComponentStyle>();
|
||||
|
||||
XDocument doc;
|
||||
try
|
||||
{
|
||||
ToolBox.IsProperFilenameCase(file);
|
||||
doc = XDocument.Load(file, LoadOptions.SetBaseUri);
|
||||
if (doc == null) { throw new Exception("doc is null"); }
|
||||
if (doc.Root == null) { throw new Exception("doc.Root is null"); }
|
||||
if (doc.Root.Elements() == null) { throw new Exception("doc.Root.Elements() is null"); }
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Loading style \"" + file + "\" failed", e);
|
||||
return;
|
||||
}
|
||||
configElement = doc.Root;
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
configElement = element;
|
||||
foreach (XElement subElement in configElement.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace Barotrauma
|
||||
|
||||
private float textDepth;
|
||||
|
||||
private ScalableFont originalFont;
|
||||
|
||||
public Vector2 TextOffset { get; set; }
|
||||
|
||||
private Vector4 padding;
|
||||
@@ -62,7 +64,7 @@ namespace Barotrauma
|
||||
set
|
||||
{
|
||||
if (base.Font == value) return;
|
||||
base.Font = value;
|
||||
base.Font = originalFont = value;
|
||||
SetTextPos();
|
||||
}
|
||||
}
|
||||
@@ -74,13 +76,23 @@ namespace Barotrauma
|
||||
{
|
||||
string newText = forceUpperCase ? value?.ToUpper() : value;
|
||||
|
||||
if (Text == newText) return;
|
||||
if (Text == newText) { return; }
|
||||
|
||||
|
||||
//reset scale, it gets recalculated in SetTextPos
|
||||
if (autoScale) textScale = 1.0f;
|
||||
if (autoScale) { textScale = 1.0f; }
|
||||
|
||||
text = newText;
|
||||
wrappedText = newText;
|
||||
if (TextManager.IsCJK(text))
|
||||
{
|
||||
//switch to fallback CJK font
|
||||
if (!Font.IsCJK) { base.Font = GUI.CJKFont; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Font == GUI.CJKFont) { base.Font = originalFont; }
|
||||
}
|
||||
SetTextPos();
|
||||
}
|
||||
}
|
||||
@@ -208,8 +220,11 @@ namespace Barotrauma
|
||||
|
||||
//if the text is in chinese/korean/japanese and we're not using a CJK-compatible font,
|
||||
//use the default CJK font as a fallback
|
||||
var selectedFont = font ?? GUI.Font;
|
||||
if (TextManager.IsCJK(text) && !selectedFont.IsCJK) { selectedFont = GUI.CJKFont; }
|
||||
var selectedFont = originalFont = font ?? GUI.Font;
|
||||
if (TextManager.IsCJK(text) && !selectedFont.IsCJK)
|
||||
{
|
||||
selectedFont = GUI.CJKFont;
|
||||
}
|
||||
this.Font = selectedFont;
|
||||
this.textAlignment = textAlignment;
|
||||
this.Wrap = wrap;
|
||||
|
||||
@@ -162,10 +162,11 @@ namespace Barotrauma
|
||||
|
||||
public override ScalableFont Font
|
||||
{
|
||||
get { return textBlock?.Font ?? base.Font; }
|
||||
set
|
||||
{
|
||||
base.Font = value;
|
||||
if (textBlock == null) return;
|
||||
if (textBlock == null) { return; }
|
||||
textBlock.Font = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Barotrauma
|
||||
{
|
||||
rectT = rectT ?? new RectTransform(new Vector2(0.25f, 1f), GUI.Canvas) { MinSize = new Point(340, GameMain.GraphicsHeight) };
|
||||
rectT.SetPosition(Anchor.TopRight);
|
||||
Parent = new GUIFrame(rectT, null, new Color(20, 20, 20, 255));
|
||||
Parent = new GUIFrame(rectT, null, Color);
|
||||
EditorBox = new GUIListBox(new RectTransform(Vector2.One * 0.98f, rectT, Anchor.Center), color: Color.Black, style: null)
|
||||
{
|
||||
Spacing = 10
|
||||
@@ -49,5 +49,7 @@ namespace Barotrauma
|
||||
{
|
||||
EditorBox = CreateEditorBox();
|
||||
}
|
||||
|
||||
public static Color Color = new Color(20, 20, 20, 255);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,9 +358,9 @@ namespace Barotrauma
|
||||
parent?.ChildrenChanged?.Invoke(this);
|
||||
}
|
||||
|
||||
public static RectTransform Load(XElement element, RectTransform parent)
|
||||
public static RectTransform Load(XElement element, RectTransform parent, Anchor defaultAnchor = Anchor.TopLeft)
|
||||
{
|
||||
Enum.TryParse(element.GetAttributeString("anchor", "Center"), out Anchor anchor);
|
||||
Enum.TryParse(element.GetAttributeString("anchor", defaultAnchor.ToString()), out Anchor anchor);
|
||||
Enum.TryParse(element.GetAttributeString("pivot", anchor.ToString()), out Pivot pivot);
|
||||
|
||||
Point? minSize = null, maxSize = null;
|
||||
@@ -368,11 +368,7 @@ namespace Barotrauma
|
||||
//if (element.Attribute("maxsize") != null) maxSize = element.GetAttributePoint("maxsize", new Point(1000, 1000));
|
||||
|
||||
RectTransform rectTransform;
|
||||
if (element.Attribute("relativesize") != null)
|
||||
{
|
||||
rectTransform = new RectTransform(element.GetAttributeVector2("relativesize", Vector2.One), parent, anchor, pivot, minSize, maxSize);
|
||||
}
|
||||
else
|
||||
if (element.Attribute("absolutesize") != null)
|
||||
{
|
||||
rectTransform = new RectTransform(element.GetAttributePoint("absolutesize", new Point(1000, 1000)), parent, anchor, pivot)
|
||||
{
|
||||
@@ -380,6 +376,10 @@ namespace Barotrauma
|
||||
maxSize = maxSize
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
rectTransform = new RectTransform(element.GetAttributeVector2("relativesize", Vector2.One), parent, anchor, pivot, minSize, maxSize);
|
||||
}
|
||||
rectTransform.RelativeOffset = element.GetAttributeVector2("relativeoffset", Vector2.Zero);
|
||||
rectTransform.AbsoluteOffset = element.GetAttributePoint("absoluteoffset", Point.Zero);
|
||||
return rectTransform;
|
||||
|
||||
@@ -16,6 +16,7 @@ using System.IO;
|
||||
using System.Threading;
|
||||
using Barotrauma.Tutorials;
|
||||
using Barotrauma.Media;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -44,7 +45,7 @@ namespace Barotrauma
|
||||
public static ParticleEditorScreen ParticleEditorScreen;
|
||||
public static LevelEditorScreen LevelEditorScreen;
|
||||
public static SpriteEditorScreen SpriteEditorScreen;
|
||||
public static CharacterEditorScreen CharacterEditorScreen;
|
||||
public static CharacterEditor.CharacterEditorScreen CharacterEditorScreen;
|
||||
|
||||
public static Lights.LightManager LightManager;
|
||||
|
||||
@@ -52,7 +53,7 @@ namespace Barotrauma
|
||||
|
||||
public static Thread MainThread { get; private set; }
|
||||
|
||||
public static HashSet<ContentPackage> SelectedPackages
|
||||
public static IEnumerable<ContentPackage> SelectedPackages
|
||||
{
|
||||
get { return Config?.SelectedContentPackages; }
|
||||
}
|
||||
@@ -171,6 +172,9 @@ namespace Barotrauma
|
||||
|
||||
GraphicsDeviceManager = new GraphicsDeviceManager(this);
|
||||
|
||||
GraphicsDeviceManager.IsFullScreen = false;
|
||||
GraphicsDeviceManager.ApplyChanges();
|
||||
|
||||
Window.Title = "Barotrauma";
|
||||
|
||||
Instance = this;
|
||||
@@ -405,7 +409,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (SelectedPackages.Count == 0)
|
||||
if (SelectedPackages.None())
|
||||
{
|
||||
DebugConsole.Log("No content packages selected");
|
||||
}
|
||||
@@ -452,7 +456,9 @@ namespace Barotrauma
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
Character.LoadAllConfigFiles();
|
||||
MissionPrefab.Init();
|
||||
TraitorMissionPrefab.Init();
|
||||
MapEntityPrefab.Init();
|
||||
Tutorials.Tutorial.Init();
|
||||
MapGenerationParams.Init();
|
||||
@@ -472,9 +478,9 @@ namespace Barotrauma
|
||||
|
||||
JobPrefab.LoadAll(GetFilesOfType(ContentType.Jobs));
|
||||
// Add any missing jobs from the prefab into Config.JobNamePreferences.
|
||||
foreach (JobPrefab job in JobPrefab.List)
|
||||
foreach (string job in JobPrefab.List.Keys)
|
||||
{
|
||||
if (!Config.JobPreferences.Contains(job.Identifier)) { Config.JobPreferences.Add(job.Identifier); }
|
||||
if (!Config.JobPreferences.Contains(job)) { Config.JobPreferences.Add(job); }
|
||||
}
|
||||
|
||||
NPCConversation.LoadAll(GetFilesOfType(ContentType.NPCConversations));
|
||||
@@ -523,7 +529,7 @@ namespace Barotrauma
|
||||
|
||||
LevelEditorScreen = new LevelEditorScreen();
|
||||
SpriteEditorScreen = new SpriteEditorScreen();
|
||||
CharacterEditorScreen = new CharacterEditorScreen();
|
||||
CharacterEditorScreen = new CharacterEditor.CharacterEditorScreen();
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
@@ -726,7 +732,7 @@ namespace Barotrauma
|
||||
GameMain.MainMenuScreen.Select();
|
||||
}
|
||||
UInt64 serverSteamId = SteamManager.SteamIDStringToUInt64(ConnectEndpoint);
|
||||
Client = new GameClient(SteamManager.GetUsername(),
|
||||
Client = new GameClient(Config.PlayerName,
|
||||
serverSteamId != 0 ? null : ConnectEndpoint,
|
||||
serverSteamId,
|
||||
string.IsNullOrWhiteSpace(ConnectName) ? ConnectEndpoint : ConnectName);
|
||||
@@ -762,8 +768,11 @@ namespace Barotrauma
|
||||
{
|
||||
GUI.TogglePauseMenu();
|
||||
}
|
||||
else if ((Character.Controlled?.SelectedConstruction == null || !Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null))
|
||||
&& Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null)
|
||||
//open the pause menu if not controlling a character OR if the character has no UIs active that can be closed with ESC
|
||||
else if (Character.Controlled == null ||
|
||||
((Character.Controlled.SelectedConstruction == null || !Character.Controlled.SelectedConstruction.ActiveHUDs.Any(ic => ic.GuiFrame != null))
|
||||
//TODO: do we need to check Inventory.SelectedSlot?
|
||||
&& Inventory.SelectedSlot == null && CharacterHealth.OpenHealthWindow == null))
|
||||
{
|
||||
// Otherwise toggle pausing, unless another window/interface is open.
|
||||
GUI.TogglePauseMenu();
|
||||
@@ -771,7 +780,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
GUI.ClearUpdateList();
|
||||
paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning) &&
|
||||
paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen || Tutorial.ContentRunning || DebugConsole.Paused) &&
|
||||
(NetworkMember == null || !NetworkMember.GameStarted);
|
||||
|
||||
#if !DEBUG
|
||||
@@ -802,6 +811,17 @@ namespace Barotrauma
|
||||
{
|
||||
(GameSession.GameMode as TutorialMode).Update((float)Timing.Step);
|
||||
}
|
||||
else if (DebugConsole.Paused)
|
||||
{
|
||||
if (Screen.Selected.Cam == null)
|
||||
{
|
||||
DebugConsole.Paused = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Screen.Selected.Cam.MoveCamera((float)Timing.Step);
|
||||
}
|
||||
}
|
||||
|
||||
if (NetworkMember != null)
|
||||
{
|
||||
@@ -908,7 +928,7 @@ namespace Barotrauma
|
||||
UserData = link.Second,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
Process.Start(userdata as string);
|
||||
ShowOpenUrlInWebBrowserPrompt(userdata as string);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -920,7 +940,6 @@ namespace Barotrauma
|
||||
Config.SaveNewPlayerConfig();
|
||||
}
|
||||
|
||||
// ToDo: Move texts/links to localization, when possible.
|
||||
public void ShowBugReporter()
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("bugreportbutton"), "");
|
||||
@@ -928,24 +947,27 @@ namespace Barotrauma
|
||||
var linkHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 1.0f), msgBox.Content.RectTransform)) { Stretch = true, RelativeSpacing = 0.025f };
|
||||
linkHolder.RectTransform.MaxSize = new Point(int.MaxValue, linkHolder.Rect.Height);
|
||||
|
||||
List<Pair<string, string>> links = new List<Pair<string, string>>()
|
||||
{
|
||||
new Pair<string, string>(TextManager.Get("bugreportfeedbackform"),"https://barotraumagame.com/feedback"),
|
||||
new Pair<string, string>(TextManager.Get("bugreportgithubform"),"https://github.com/Regalis11/Barotrauma/issues/new?template=bug_report.md")
|
||||
};
|
||||
foreach (var link in links)
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), linkHolder.RectTransform), TextManager.Get("bugreportfeedbackform"), style: "MainMenuGUIButton", textAlignment: Alignment.Left)
|
||||
{
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), linkHolder.RectTransform), link.First, style: "MainMenuGUIButton", textAlignment: Alignment.Left)
|
||||
UserData = "https://steamcommunity.com/app/602960/discussions/1/",
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
UserData = link.Second,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
Process.Start(userdata as string);
|
||||
msgBox.Close();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
SteamManager.OverlayCustomURL(userdata as string);
|
||||
msgBox.Close();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
new GUIButton(new RectTransform(new Vector2(1.0f, 1.0f), linkHolder.RectTransform), TextManager.Get("bugreportgithubform"), style: "MainMenuGUIButton", textAlignment: Alignment.Left)
|
||||
{
|
||||
UserData = "https://github.com/Regalis11/Barotrauma/issues/new?template=bug_report.md",
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
ShowOpenUrlInWebBrowserPrompt(userdata as string);
|
||||
msgBox.Close();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
msgBox.InnerFrame.RectTransform.MinSize = new Point(0,
|
||||
msgBox.InnerFrame.Rect.Height + linkHolder.Rect.Height + msgBox.Content.AbsoluteSpacing * 2 + (int)(50 * GUI.Scale));
|
||||
@@ -968,5 +990,24 @@ namespace Barotrauma
|
||||
if (GameSettings.SaveDebugConsoleLogs) DebugConsole.SaveLogs();
|
||||
base.OnExiting(sender, args);
|
||||
}
|
||||
|
||||
public void ShowOpenUrlInWebBrowserPrompt(string url)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url)) { return; }
|
||||
if (GUIMessageBox.VisibleBox?.UserData as string == "verificationprompt") { return; }
|
||||
|
||||
var msgBox = new GUIMessageBox("", TextManager.GetWithVariable("openlinkinbrowserprompt", "[link]", url),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") })
|
||||
{
|
||||
UserData = "verificationprompt"
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
Process.Start(url);
|
||||
msgBox.Close();
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +172,11 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
var reports = Order.PrefabList.FindAll(o => o.TargetAllCharacters && o.SymbolSprite != null);
|
||||
if (reports.None())
|
||||
{
|
||||
DebugConsole.ThrowError("No valid orders for report buttons found! Cannot create report buttons. The orders for the report buttons must have 'targetallcharacters' attribute enabled and a valid 'symbolsprite' defined.");
|
||||
return;
|
||||
}
|
||||
reportButtonFrame = new GUILayoutGroup(new RectTransform(
|
||||
new Point((HUDLayoutSettings.CrewArea.Height - (int)((reports.Count - 1) * 5 * GUI.Scale)) / reports.Count, HUDLayoutSettings.CrewArea.Height), guiFrame.RectTransform))
|
||||
{
|
||||
@@ -322,7 +327,7 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
private GUIComponent CreateCharacterFrame(Character character, GUIComponent parent)
|
||||
{
|
||||
int correctOrderCount = 0, neutralOrderCount = 0, wrongOrderCount = 0;
|
||||
int genericOrderCount = 0, correctOrderCount = 0, wrongOrderCount = 0;
|
||||
//sort the orders
|
||||
// 1. generic orders (follow, wait, etc)
|
||||
// 2. orders appropriate for the character's job (captain -> steer, etc)
|
||||
@@ -331,15 +336,16 @@ namespace Barotrauma
|
||||
foreach (Order order in Order.PrefabList)
|
||||
{
|
||||
if (order.TargetAllCharacters || order.SymbolSprite == null) continue;
|
||||
if (order.AppropriateJobs == null || order.AppropriateJobs.Length == 0)
|
||||
if (!JobPrefab.List.Values.Any(jp => jp.AppropriateOrders.Contains(order.Identifier)) &&
|
||||
(order.AppropriateJobs == null || !order.AppropriateJobs.Any()))
|
||||
{
|
||||
orders.Insert(0, order);
|
||||
correctOrderCount++;
|
||||
genericOrderCount++;
|
||||
}
|
||||
else if (order.HasAppropriateJob(character))
|
||||
{
|
||||
orders.Add(order);
|
||||
neutralOrderCount++;
|
||||
correctOrderCount++;
|
||||
}
|
||||
}
|
||||
foreach (Order order in Order.PrefabList)
|
||||
@@ -481,7 +487,7 @@ namespace Barotrauma
|
||||
var order = orders[i];
|
||||
if (order.TargetAllCharacters) continue;
|
||||
|
||||
RectTransform btnParent = (i >= correctOrderCount + neutralOrderCount) ?
|
||||
RectTransform btnParent = (i >= genericOrderCount + correctOrderCount) ?
|
||||
wrongOrderList.Content.RectTransform :
|
||||
orderButtonFrame.RectTransform;
|
||||
|
||||
@@ -516,7 +522,7 @@ namespace Barotrauma
|
||||
|
||||
if (btn.GetChildByUserData("selected").Visible)
|
||||
{
|
||||
SetCharacterOrder(character, Order.PrefabList.Find(o => o.AITag == "dismissed"), null, Character.Controlled);
|
||||
SetCharacterOrder(character, Order.GetPrefab("dismissed"), null, Character.Controlled);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -535,7 +541,7 @@ namespace Barotrauma
|
||||
btn.ToolTip = order.Name;
|
||||
|
||||
//divider between different groups of orders
|
||||
if (i == correctOrderCount - 1 || i == correctOrderCount + neutralOrderCount - 1)
|
||||
if (i == genericOrderCount - 1 || i == genericOrderCount + correctOrderCount - 1)
|
||||
{
|
||||
//TODO: divider sprite
|
||||
new GUIFrame(new RectTransform(new Point(8, iconSize), orderButtonFrame.RectTransform), style: "GUIButton");
|
||||
@@ -999,14 +1005,15 @@ namespace Barotrauma
|
||||
color: matchingItems.Count > 1 ? Color.Black * 0.9f : Color.Black * 0.7f);
|
||||
}
|
||||
|
||||
public void HighlightOrderButton(Character character, string orderAiTag, Color color, Vector2? flashRectInflate = null)
|
||||
public void HighlightOrderButton(Character character, string orderIdentifier, Color color, Vector2? flashRectInflate = null)
|
||||
{
|
||||
var order = Order.PrefabList.Find(o => o.AITag == orderAiTag);
|
||||
var order = Order.GetPrefab(orderIdentifier);
|
||||
if (order == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find an order with the AI tag \"" + orderAiTag + "\".\n" + Environment.StackTrace);
|
||||
DebugConsole.ThrowError("Could not find an order with the AI tag \"" + orderIdentifier + "\".\n" + Environment.StackTrace);
|
||||
return;
|
||||
}
|
||||
ToggleCrewAreaOpen = true;
|
||||
var characterElement = characterListBox.Content.FindChild(character);
|
||||
GUIButton orderBtn = characterElement.FindChild(order, recursive: true) as GUIButton;
|
||||
if (orderBtn.Frame.FlashTimer <= 0)
|
||||
@@ -1417,14 +1424,14 @@ namespace Barotrauma
|
||||
// return true;
|
||||
//}
|
||||
|
||||
private void ToggleReportButton(string orderAiTag, bool enabled)
|
||||
private void ToggleReportButton(string orderIdentifier, bool enabled)
|
||||
{
|
||||
Order order = Order.PrefabList.Find(o => o.AITag == orderAiTag);
|
||||
Order order = Order.GetPrefab(orderIdentifier);
|
||||
|
||||
//already reported, disable the button
|
||||
/*if (GameMain.GameSession.CrewManager.ActiveOrders.Any(o =>
|
||||
o.First.TargetEntity == Character.Controlled.CurrentHull &&
|
||||
o.First.AITag == orderAiTag))
|
||||
o.First.Identifier == orderIdentifier))
|
||||
{
|
||||
enabled = false;
|
||||
}*/
|
||||
|
||||
@@ -9,8 +9,9 @@ namespace Barotrauma
|
||||
{
|
||||
if (Mission == null) return;
|
||||
|
||||
new GUIMessageBox(Mission.Name, Mission.Description, new Vector2(0.25f, 0.0f), new Point(400, 200))
|
||||
new GUIMessageBox(Mission.Name, Mission.Description, new string[0], type: GUIMessageBox.Type.InGame, icon: Mission.Prefab.Icon)
|
||||
{
|
||||
IconColor = Mission.Prefab.IconColor,
|
||||
UserData = "missionstartmessage"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -138,6 +138,7 @@ namespace Barotrauma
|
||||
msg.Write(map.SelectedMissionIndex == -1 ? byte.MaxValue : (byte)map.SelectedMissionIndex);
|
||||
msg.Write(PurchasedHullRepairs);
|
||||
msg.Write(PurchasedItemRepairs);
|
||||
msg.Write(PurchasedLostShuttles);
|
||||
|
||||
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
||||
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
|
||||
@@ -164,6 +165,7 @@ namespace Barotrauma
|
||||
int money = msg.ReadInt32();
|
||||
bool purchasedHullRepairs = msg.ReadBoolean();
|
||||
bool purchasedItemRepairs = msg.ReadBoolean();
|
||||
bool purchasedLostShuttles = msg.ReadBoolean();
|
||||
|
||||
UInt16 purchasedItemCount = msg.ReadUInt16();
|
||||
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
||||
@@ -178,7 +180,7 @@ namespace Barotrauma
|
||||
CharacterInfo myCharacterInfo = null;
|
||||
if (hasCharacterData)
|
||||
{
|
||||
myCharacterInfo = CharacterInfo.ClientRead(Character.HumanConfigFile, msg);
|
||||
myCharacterInfo = CharacterInfo.ClientRead(Character.HumanSpeciesName, msg);
|
||||
}
|
||||
|
||||
MultiPlayerCampaign campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||
@@ -226,6 +228,7 @@ namespace Barotrauma
|
||||
campaign.Money = money;
|
||||
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
||||
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
||||
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
||||
campaign.CargoManager.SetPurchasedItems(purchasedItems);
|
||||
|
||||
if (myCharacterInfo != null)
|
||||
@@ -239,7 +242,6 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
campaign.lastUpdateID = updateID;
|
||||
|
||||
campaign.SuppressStateSending = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@ namespace Barotrauma
|
||||
OnClicked = (btn, userdata) => { TryEndRound(GetLeavingSub()); return true; }
|
||||
};
|
||||
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.List)
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.List.Values)
|
||||
{
|
||||
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
||||
{
|
||||
CrewManager.AddCharacterInfo(new CharacterInfo(Character.HumanConfigFile, "", jobPrefab));
|
||||
CrewManager.AddCharacterInfo(new CharacterInfo(Character.HumanSpeciesName, "", jobPrefab));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,6 +175,11 @@ namespace Barotrauma
|
||||
|
||||
protected override void WatchmanInteract(Character watchman, Character interactor)
|
||||
{
|
||||
if (interactor != null)
|
||||
{
|
||||
interactor.FocusedCharacter = null;
|
||||
}
|
||||
|
||||
Submarine leavingSub = GetLeavingSub();
|
||||
if (leavingSub == null)
|
||||
{
|
||||
@@ -182,7 +187,6 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CreateDialog(new List<Character> { watchman }, "WatchmanInteract", 1.0f);
|
||||
|
||||
if (GUIMessageBox.MessageBoxes.Any(mbox => mbox.UserData as string == "watchmanprompt"))
|
||||
@@ -295,7 +299,7 @@ namespace Barotrauma
|
||||
{
|
||||
GameMain.GameSession.LoadPrevious();
|
||||
GameMain.LobbyScreen.Select();
|
||||
GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox);
|
||||
GUIMessageBox.MessageBoxes.RemoveAll(c => c?.UserData as string == "roundsummary");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -303,7 +307,11 @@ namespace Barotrauma
|
||||
var quitButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), buttonArea.RectTransform),
|
||||
TextManager.Get("QuitButton"));
|
||||
quitButton.OnClicked += GameMain.LobbyScreen.QuitToMainMenu;
|
||||
quitButton.OnClicked += (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(GUIMessageBox.VisibleBox); return true; };
|
||||
quitButton.OnClicked += (GUIButton button, object obj) =>
|
||||
{
|
||||
GUIMessageBox.MessageBoxes.RemoveAll(c => c?.UserData as string == "roundsummary");
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -295,9 +295,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
var moloch = Character.Create(
|
||||
"Content/Characters/Moloch/moloch.xml",
|
||||
steering.Item.WorldPosition + new Vector2(3000.0f, -500.0f), "");
|
||||
var moloch = Character.Create("moloch", steering.Item.WorldPosition + new Vector2(3000.0f, -500.0f), "");
|
||||
|
||||
moloch.PlaySound(CharacterSound.SoundType.Attack);
|
||||
|
||||
@@ -663,7 +661,7 @@ namespace Barotrauma.Tutorials
|
||||
//TODO: reimplement
|
||||
//enemy.Health = 50.0f;
|
||||
|
||||
enemy.AIController.State = AIController.AIState.Idle;
|
||||
enemy.AIController.State = AIState.Idle;
|
||||
|
||||
Vector2 targetPos = Character.Controlled.WorldPosition + new Vector2(0.0f, 3000.0f);
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Barotrauma.Tutorials
|
||||
captainsuniform.Unequip(captain);
|
||||
captain.Inventory.RemoveItem(captainsuniform);
|
||||
|
||||
var steerOrder = Order.PrefabList.Find(order => order.AITag == "steer");
|
||||
var steerOrder = Order.GetPrefab("steer");
|
||||
captain_steerIcon = steerOrder.SymbolSprite;
|
||||
captain_steerIconColor = steerOrder.Color;
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Barotrauma.Tutorials
|
||||
captain_medicSpawnPos = Item.ItemList.Find(i => i.HasTag("captain_medicspawnpos")).WorldPosition;
|
||||
tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent<Door>();
|
||||
tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent<LightComponent>();
|
||||
var medicInfo = new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "medicaldoctor"));
|
||||
var medicInfo = new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("medicaldoctor"));
|
||||
captain_medic = Character.Create(medicInfo, captain_medicSpawnPos, "medicaldoctor");
|
||||
captain_medic.GiveJobItems(null);
|
||||
captain_medic.CanSpeak = captain_medic.AIController.Enabled = false;
|
||||
@@ -107,15 +107,15 @@ namespace Barotrauma.Tutorials
|
||||
SetDoorAccess(tutorial_lockedDoor_1, null, false);
|
||||
SetDoorAccess(tutorial_lockedDoor_2, null, false);
|
||||
|
||||
var mechanicInfo = new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "mechanic"));
|
||||
var mechanicInfo = new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("mechanic"));
|
||||
captain_mechanic = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "mechanic");
|
||||
captain_mechanic.GiveJobItems();
|
||||
|
||||
var securityInfo = new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "securityofficer"));
|
||||
var securityInfo = new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("securityofficer"));
|
||||
captain_security = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "securityofficer");
|
||||
captain_security.GiveJobItems();
|
||||
|
||||
var engineerInfo = new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "engineer"));
|
||||
var engineerInfo = new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
||||
captain_engineer = Character.Create(engineerInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "engineer");
|
||||
captain_engineer.GiveJobItems();
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Barotrauma.Tutorials
|
||||
{
|
||||
base.Start();
|
||||
|
||||
var firstAidOrder = Order.PrefabList.Find(order => order.AITag == "requestfirstaid");
|
||||
var firstAidOrder = Order.GetPrefab("requestfirstaid");
|
||||
doctor_firstAidIcon = firstAidOrder.SymbolSprite;
|
||||
doctor_firstAidIconColor = firstAidOrder.Color;
|
||||
|
||||
@@ -63,30 +63,30 @@ namespace Barotrauma.Tutorials
|
||||
var patientHull2 = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "airlock").CurrentHull;
|
||||
medBay = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "medbay").CurrentHull;
|
||||
|
||||
var assistantInfo = new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "assistant"));
|
||||
var assistantInfo = new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("assistant"));
|
||||
patient1 = Character.Create(assistantInfo, patientHull1.WorldPosition, "1");
|
||||
patient1.GiveJobItems(null);
|
||||
patient1.CanSpeak = false;
|
||||
patient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 45.0f) }, stun: 0, playSound: false);
|
||||
patient1.AIController.Enabled = false;
|
||||
|
||||
assistantInfo = new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "assistant"));
|
||||
|
||||
assistantInfo = new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("assistant"));
|
||||
patient2 = Character.Create(assistantInfo, patientHull2.WorldPosition, "2");
|
||||
patient2.GiveJobItems(null);
|
||||
patient2.CanSpeak = false;
|
||||
patient2.AIController.Enabled = false;
|
||||
|
||||
var mechanicInfo = new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "engineer"));
|
||||
var mechanicInfo = new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
||||
var subPatient1 = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
||||
subPatient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 40.0f) }, stun: 0, playSound: false);
|
||||
subPatients.Add(subPatient1);
|
||||
|
||||
var securityInfo = new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "securityofficer"));
|
||||
var securityInfo = new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("securityofficer"));
|
||||
var subPatient2 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
||||
subPatient2.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.InternalDamage, 40.0f) }, stun: 0, playSound: false);
|
||||
subPatients.Add(subPatient2);
|
||||
|
||||
var engineerInfo = new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "engineer"));
|
||||
var engineerInfo = new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("engineer"));
|
||||
var subPatient3 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job, Submarine.MainSub).WorldPosition, "3");
|
||||
subPatient3.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 20.0f) }, stun: 0, playSound: false);
|
||||
subPatients.Add(subPatient3);
|
||||
@@ -240,7 +240,7 @@ namespace Barotrauma.Tutorials
|
||||
// treat patient --------------------------------------------------------------------------------------------
|
||||
|
||||
//patient 1 requests first aid
|
||||
var newOrder = new Order(Order.PrefabList.Find(o => o.AITag == "requestfirstaid"), patient1.CurrentHull, null, orderGiver: patient1);
|
||||
var newOrder = new Order(Order.GetPrefab("requestfirstaid"), patient1.CurrentHull, null, orderGiver: patient1);
|
||||
doctor.AddActiveObjectiveEntity(patient1, doctor_firstAidIcon, doctor_firstAidIconColor);
|
||||
//GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient1.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
@@ -263,7 +263,7 @@ namespace Barotrauma.Tutorials
|
||||
doctor.RemoveActiveObjectiveEntity(patient1);
|
||||
TriggerTutorialSegment(3); // Get the patient to medbay
|
||||
|
||||
while (patient1.CurrentOrder == null || patient1.CurrentOrder.AITag != "follow")
|
||||
while (patient1.CurrentOrder == null || patient1.CurrentOrder.Identifier != "follow")
|
||||
{
|
||||
GameMain.GameSession.CrewManager.HighlightOrderButton(patient1, "follow", highlightColor, new Vector2(5, 5));
|
||||
yield return null;
|
||||
@@ -329,7 +329,7 @@ namespace Barotrauma.Tutorials
|
||||
//patient calls for help
|
||||
//patient2.CanSpeak = true;
|
||||
yield return new WaitForSeconds(2.0f, false);
|
||||
newOrder = new Order(Order.PrefabList.Find(o => o.AITag == "requestfirstaid"), patient2.CurrentHull, null, orderGiver: patient2);
|
||||
newOrder = new Order(Order.GetPrefab("requestfirstaid"), patient2.CurrentHull, null, orderGiver: patient2);
|
||||
doctor.AddActiveObjectiveEntity(patient2, doctor_firstAidIcon, doctor_firstAidIconColor);
|
||||
//GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient2.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
@@ -396,7 +396,7 @@ namespace Barotrauma.Tutorials
|
||||
if (!patientCalledHelp[i] && Timing.TotalTime > subEnterTime + 60 * (i + 1))
|
||||
{
|
||||
doctor.AddActiveObjectiveEntity(subPatients[i], doctor_firstAidIcon, doctor_firstAidIconColor);
|
||||
newOrder = new Order(Order.PrefabList.Find(o => o.AITag == "requestfirstaid"), subPatients[i].CurrentHull, null, orderGiver: subPatients[i]);
|
||||
newOrder = new Order(Order.GetPrefab("requestfirstaid"), subPatients[i].CurrentHull, null, orderGiver: subPatients[i]);
|
||||
string message = newOrder.GetChatMessage("", subPatients[i].CurrentHull?.DisplayName, givingOrderToSelf: false);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(subPatients[i].Name, message, ChatMessageType.Order, null);
|
||||
patientCalledHelp[i] = true;
|
||||
|
||||
@@ -91,11 +91,11 @@ namespace Barotrauma.Tutorials
|
||||
toolbox.Unequip(engineer);
|
||||
engineer.Inventory.RemoveItem(toolbox);
|
||||
|
||||
var repairOrder = Order.PrefabList.Find(order => order.AITag == "repairsystems");
|
||||
var repairOrder = Order.GetPrefab("repairsystems");
|
||||
engineer_repairIcon = repairOrder.SymbolSprite;
|
||||
engineer_repairIconColor = repairOrder.Color;
|
||||
|
||||
var reactorOrder = Order.PrefabList.Find(order => order.AITag == "operatereactor");
|
||||
var reactorOrder = Order.GetPrefab("operatereactor");
|
||||
engineer_reactorIcon = reactorOrder.SymbolSprite;
|
||||
engineer_reactorIconColor = reactorOrder.Color;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace Barotrauma.Tutorials
|
||||
crowbar.Unequip(mechanic);
|
||||
mechanic.Inventory.RemoveItem(crowbar);
|
||||
|
||||
var repairOrder = Order.PrefabList.Find(order => order.AITag == "repairsystems");
|
||||
var repairOrder = Order.GetPrefab("repairsystems");
|
||||
mechanic_repairIcon = repairOrder.SymbolSprite;
|
||||
mechanic_repairIconColor = repairOrder.Color;
|
||||
mechanic_weldIcon = new Sprite("Content/UI/IconAtlas.png", new Rectangle(1, 256, 127, 127), new Vector2(0.5f, 0.5f));
|
||||
|
||||
@@ -74,18 +74,12 @@ namespace Barotrauma.Tutorials
|
||||
// Variables
|
||||
private string radioSpeakerName;
|
||||
private Character officer;
|
||||
private string crawlerCharacterFile;
|
||||
private string hammerheadCharacterFile;
|
||||
private string mudraptorCharacterFile;
|
||||
private float superCapacitorRechargeRate = 10;
|
||||
private Sprite officer_gunIcon;
|
||||
private Color officer_gunIconColor;
|
||||
|
||||
public OfficerTutorial(XElement element) : base(element)
|
||||
{
|
||||
crawlerCharacterFile = Character.GetConfigFile("crawler");
|
||||
hammerheadCharacterFile = Character.GetConfigFile("hammerhead");
|
||||
mudraptorCharacterFile = Character.GetConfigFile("mudraptor");
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
@@ -111,7 +105,7 @@ namespace Barotrauma.Tutorials
|
||||
bodyarmor.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(bodyarmor);
|
||||
|
||||
var gunOrder = Order.PrefabList.Find(order => order.AITag == "operateweapons");
|
||||
var gunOrder = Order.GetPrefab("operateweapons");
|
||||
officer_gunIcon = gunOrder.SymbolSprite;
|
||||
officer_gunIconColor = gunOrder.Color;
|
||||
|
||||
@@ -267,7 +261,7 @@ namespace Barotrauma.Tutorials
|
||||
// Room 3
|
||||
do { yield return null; } while (!officer_crawlerSensor.MotionDetected);
|
||||
TriggerTutorialSegment(2);
|
||||
officer_crawler = SpawnMonster(crawlerCharacterFile, officer_crawlerSpawnPos);
|
||||
officer_crawler = SpawnMonster("crawler", officer_crawlerSpawnPos);
|
||||
do { yield return null; } while (!officer_crawler.IsDead);
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
Heal(officer);
|
||||
@@ -298,7 +292,7 @@ namespace Barotrauma.Tutorials
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
TriggerTutorialSegment(4, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Shoot), GameMain.Config.KeyBind(InputType.Deselect)); // Kill hammerhead
|
||||
officer_hammerhead = SpawnMonster(hammerheadCharacterFile, officer_hammerheadSpawnPos);
|
||||
officer_hammerhead = SpawnMonster("hammerhead", officer_hammerheadSpawnPos);
|
||||
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
|
||||
SetHighlight(officer_coilgunPeriscope, true);
|
||||
float originalDistance = Vector2.Distance(officer_coilgunPeriscope.WorldPosition, officer_hammerheadSpawnPos);
|
||||
@@ -314,8 +308,8 @@ namespace Barotrauma.Tutorials
|
||||
{
|
||||
// Ensure that the Hammerhead targets the player
|
||||
officer_hammerhead.AIController.SelectTarget(officer.AiTarget);
|
||||
var ai = officer_hammerhead.AIController as EnemyAIController;
|
||||
ai.sight = 2.0f;
|
||||
/*var ai = officer_hammerhead.AIController as EnemyAIController;
|
||||
ai.sight = 2.0f;*/
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
@@ -381,7 +375,7 @@ namespace Barotrauma.Tutorials
|
||||
// Room 6
|
||||
do { yield return null; } while (!officer_mudraptorObjectiveSensor.MotionDetected);
|
||||
TriggerTutorialSegment(6);
|
||||
officer_mudraptor = SpawnMonster(mudraptorCharacterFile, officer_mudraptorSpawnPos);
|
||||
officer_mudraptor = SpawnMonster("mudraptor", officer_mudraptorSpawnPos);
|
||||
do { yield return null; } while (!officer_mudraptor.IsDead);
|
||||
Heal(officer);
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
@@ -447,9 +441,9 @@ namespace Barotrauma.Tutorials
|
||||
return officer?.SelectedConstruction == item;
|
||||
}
|
||||
|
||||
private Character SpawnMonster(string characterFile, Vector2 pos)
|
||||
private Character SpawnMonster(string speciesName, Vector2 pos)
|
||||
{
|
||||
var character = Character.Create(characterFile, pos, ToolBox.RandomSeed(8));
|
||||
var character = Character.Create(speciesName, pos, ToolBox.RandomSeed(8));
|
||||
var ai = character.AIController as EnemyAIController;
|
||||
ai.TargetOutposts = true;
|
||||
character.CharacterHealth.SetVitality(character.Health / 2);
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace Barotrauma.Tutorials
|
||||
Submarine.MainSub.GodMode = true;
|
||||
|
||||
CharacterInfo charInfo = configElement.Element("Character") == null ?
|
||||
new CharacterInfo(Character.HumanConfigFile, "", JobPrefab.List.Find(jp => jp.Identifier == "engineer")) :
|
||||
new CharacterInfo(Character.HumanSpeciesName, "", JobPrefab.Get("engineer")) :
|
||||
new CharacterInfo(configElement.Element("Character"));
|
||||
|
||||
WayPoint wayPoint = GetSpawnPoint(charInfo);
|
||||
@@ -176,9 +176,9 @@ namespace Barotrauma.Tutorials
|
||||
return WayPoint.GetRandom(spawnPointType, charInfo.Job, spawnSub);
|
||||
}
|
||||
|
||||
protected bool HasOrder(Character character, string aiTag, string option = null)
|
||||
protected bool HasOrder(Character character, string identifier, string option = null)
|
||||
{
|
||||
if (character.CurrentOrder?.AITag == aiTag)
|
||||
if (character.CurrentOrder?.Identifier == identifier)
|
||||
{
|
||||
if (option == null)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,10 @@ namespace Barotrauma
|
||||
SoundPlayer.OverrideMusicDuration = 18.0f;
|
||||
}
|
||||
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker");
|
||||
GUIFrame frame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas), style: "GUIBackgroundBlocker")
|
||||
{
|
||||
UserData = "roundsummary"
|
||||
};
|
||||
|
||||
int width = 760, height = 500;
|
||||
GUIFrame innerFrame = new GUIFrame(new RectTransform(new Vector2(0.4f, 0.5f), frame.RectTransform, Anchor.Center, minSize: new Point(width, height)));
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace Barotrauma
|
||||
|
||||
private readonly Point MinSupportedResolution = new Point(1024, 540);
|
||||
|
||||
private bool contentPackageSelectionDirty;
|
||||
|
||||
private GUIFrame settingsFrame;
|
||||
private GUIButton applyButton;
|
||||
|
||||
@@ -122,18 +124,28 @@ namespace Barotrauma
|
||||
}
|
||||
if (!contentPackage.IsCompatible())
|
||||
{
|
||||
tickBox.TextColor = Color.Red;
|
||||
tickBox.Enabled = false;
|
||||
tickBox.ToolTip = TextManager.GetWithVariables(contentPackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage",
|
||||
tickBox.TextColor = Color.Red * 0.6f;
|
||||
tickBox.ToolTip = tickBox.TextBlock.ToolTip =
|
||||
TextManager.GetWithVariables(contentPackage.GameVersion <= new Version(0, 0, 0, 0) ? "IncompatibleContentPackageUnknownVersion" : "IncompatibleContentPackage",
|
||||
new string[3] { "[packagename]", "[packageversion]", "[gameversion]" }, new string[3] { contentPackage.Name, contentPackage.GameVersion.ToString(), GameMain.Version.ToString() });
|
||||
}
|
||||
else if (contentPackage.CorePackage && !contentPackage.ContainsRequiredCorePackageFiles(out List<ContentType> missingContentTypes))
|
||||
{
|
||||
tickBox.TextColor = Color.Red;
|
||||
tickBox.Enabled = false;
|
||||
tickBox.ToolTip = TextManager.GetWithVariables("ContentPackageMissingCoreFiles", new string[2] { "[packagename]", "[missingfiletypes]" },
|
||||
tickBox.TextColor = Color.Red * 0.6f;
|
||||
tickBox.ToolTip = tickBox.TextBlock.ToolTip =
|
||||
TextManager.GetWithVariables("ContentPackageMissingCoreFiles", new string[2] { "[packagename]", "[missingfiletypes]" },
|
||||
new string[2] { contentPackage.Name, string.Join(", ", missingContentTypes) }, new bool[2] { false, true });
|
||||
}
|
||||
else if (contentPackage.Invalid)
|
||||
{
|
||||
tickBox.Enabled = false;
|
||||
tickBox.TextColor = Color.Red * 0.6f;
|
||||
tickBox.ToolTip = tickBox.TextBlock.ToolTip =
|
||||
TextManager.GetWithVariable("InvalidContentPackage", "[packagename]", contentPackage.Name) +
|
||||
"\n" + string.Join("\n", contentPackage.ErrorMessages);
|
||||
}
|
||||
}
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.045f), generalLayoutGroup.RectTransform), TextManager.Get("Language"));
|
||||
@@ -147,12 +159,28 @@ namespace Barotrauma
|
||||
languageDD.OnSelected = (guiComponent, obj) =>
|
||||
{
|
||||
string newLanguage = obj as string;
|
||||
if (newLanguage == Language) return true;
|
||||
|
||||
if (newLanguage == Language) { return true; }
|
||||
|
||||
string prevLanguage = Language;
|
||||
Language = newLanguage;
|
||||
UnsavedSettings = true;
|
||||
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredLanguage"));
|
||||
var msgBox = new GUIMessageBox(
|
||||
TextManager.Get("RestartRequiredLabel"),
|
||||
TextManager.Get("RestartRequiredLanguage"),
|
||||
buttons: new string[] { TextManager.Get("Cancel"), TextManager.Get("OK") });
|
||||
msgBox.Buttons[0].OnClicked += (btn, userdata) =>
|
||||
{
|
||||
Language = prevLanguage;
|
||||
languageDD.SelectItem(Language);
|
||||
msgBox.Close();
|
||||
return true;
|
||||
}; msgBox.Buttons[1].OnClicked += (btn, userdata) =>
|
||||
{
|
||||
ApplySettings();
|
||||
GameMain.Instance.Exit();
|
||||
return true;
|
||||
};
|
||||
|
||||
return true;
|
||||
};
|
||||
@@ -586,7 +614,7 @@ namespace Barotrauma
|
||||
BarScroll = (float)Math.Sqrt(MathUtils.InverseLerp(0.2f, 5.0f, MicrophoneVolume)),
|
||||
OnMoved = (scrollBar, scroll) =>
|
||||
{
|
||||
MicrophoneVolume = MathHelper.Lerp(0.2f, 5.0f, scroll * scroll);
|
||||
MicrophoneVolume = MathHelper.Lerp(0.2f, 10.0f, scroll * scroll);
|
||||
MicrophoneVolume = (float)Math.Round(MicrophoneVolume, 1);
|
||||
ChangeSliderText(scrollBar, MicrophoneVolume);
|
||||
scrollBar.Step = 0.05f;
|
||||
@@ -630,7 +658,7 @@ namespace Barotrauma
|
||||
noiseGateSlider.Frame.Visible = false;
|
||||
noiseGateSlider.Step = 0.01f;
|
||||
noiseGateSlider.Range = new Vector2(-100.0f, 0.0f);
|
||||
noiseGateSlider.BarScroll = MathUtils.InverseLerp(-1.0f, 0.0f, NoiseGateThreshold);
|
||||
noiseGateSlider.BarScroll = MathUtils.InverseLerp(-100.0f, 0.0f, NoiseGateThreshold);
|
||||
noiseGateSlider.BarScroll *= noiseGateSlider.BarScroll;
|
||||
noiseGateSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
@@ -976,14 +1004,15 @@ namespace Barotrauma
|
||||
|
||||
private bool SelectContentPackage(GUITickBox tickBox)
|
||||
{
|
||||
contentPackageSelectionDirty = true;
|
||||
var contentPackage = tickBox.UserData as ContentPackage;
|
||||
if (contentPackage.CorePackage)
|
||||
{
|
||||
if (tickBox.Selected)
|
||||
{
|
||||
//make sure no other core packages are selected
|
||||
SelectedContentPackages.RemoveWhere(cp => cp.CorePackage && cp != contentPackage);
|
||||
SelectedContentPackages.Add(contentPackage);
|
||||
SelectedContentPackages.RemoveAll(cp => cp.CorePackage && cp != contentPackage);
|
||||
SelectContentPackage(contentPackage);
|
||||
foreach (GUITickBox otherTickBox in tickBox.Parent.Children)
|
||||
{
|
||||
ContentPackage otherContentPackage = otherTickBox.UserData as ContentPackage;
|
||||
@@ -1003,11 +1032,11 @@ namespace Barotrauma
|
||||
{
|
||||
if (tickBox.Selected)
|
||||
{
|
||||
SelectedContentPackages.Add(contentPackage);
|
||||
SelectContentPackage(contentPackage);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedContentPackages.Remove(contentPackage);
|
||||
DeselectContentPackage(contentPackage);
|
||||
}
|
||||
}
|
||||
if (contentPackage.GetFilesOfType(ContentType.Submarine).Any()) { Submarine.RefreshSavedSubs(); }
|
||||
@@ -1128,7 +1157,10 @@ namespace Barotrauma
|
||||
{
|
||||
ApplySettings();
|
||||
if (Screen.Selected != GameMain.MainMenuScreen) GUI.SettingsMenuOpen = false;
|
||||
|
||||
if (contentPackageSelectionDirty)
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("RestartRequiredLabel"), TextManager.Get("RestartRequiredGeneric"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,13 @@ namespace Barotrauma
|
||||
if (item == null) return null;
|
||||
|
||||
var container = item.GetComponent<ItemContainer>();
|
||||
if (container == null || !container.KeepOpenWhenEquipped || !character.HasEquippedItem(container.Item)) return null;
|
||||
if (container == null ||
|
||||
!character.CanAccessInventory(container.Inventory) ||
|
||||
!container.KeepOpenWhenEquipped ||
|
||||
!character.HasEquippedItem(container.Item))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return container.Inventory;
|
||||
}
|
||||
@@ -133,7 +139,7 @@ namespace Barotrauma
|
||||
|
||||
public override void CreateSlots()
|
||||
{
|
||||
if (slots == null) slots = new InventorySlot[capacity];
|
||||
if (slots == null) { slots = new InventorySlot[capacity]; }
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
@@ -179,9 +185,11 @@ namespace Barotrauma
|
||||
highlightedSubInventorySlots.RemoveWhere(s => s.Inventory.OpenState <= 0.0f);
|
||||
foreach (var subSlot in highlightedSubInventorySlots)
|
||||
{
|
||||
subSlot.Slot = slots[subSlot.SlotIndex];
|
||||
if (subSlot.ParentInventory == this && subSlot.SlotIndex > 0 && subSlot.SlotIndex < slots.Length)
|
||||
{
|
||||
subSlot.Slot = slots[subSlot.SlotIndex];
|
||||
}
|
||||
}
|
||||
//highlightedSubInventorySlots.Clear();
|
||||
|
||||
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
CalculateBackgroundFrame();
|
||||
@@ -475,7 +483,9 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
List<SlotReference> hideSubInventories = new List<SlotReference>();
|
||||
highlightedSubInventorySlots.RemoveWhere(s => s.SlotIndex < 0 || s.SlotIndex >= Items.Length || Items[s.SlotIndex] == null);
|
||||
highlightedSubInventorySlots.RemoveWhere(s =>
|
||||
s.ParentInventory == this &&
|
||||
((s.SlotIndex < 0 || s.SlotIndex >= Items.Length || Items[s.SlotIndex] == null) || (Character.Controlled != null && !Character.Controlled.CanAccessInventory(s.Inventory))));
|
||||
foreach (var highlightedSubInventorySlot in highlightedSubInventorySlots)
|
||||
{
|
||||
if (highlightedSubInventorySlot.ParentInventory == this)
|
||||
@@ -522,6 +532,9 @@ namespace Barotrauma
|
||||
|
||||
if (character.SelectedCharacter == null) // Permanently open subinventories only available when the default UI layout is in use -> not when grabbing characters
|
||||
{
|
||||
//remove the highlighted slots of other characters' inventories when not grabbing anyone
|
||||
highlightedSubInventorySlots.RemoveWhere(s => s.ParentInventory != this && s.ParentInventory?.Owner is Character);
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
var item = Items[i];
|
||||
@@ -531,7 +544,10 @@ namespace Barotrauma
|
||||
if (character.HasEquippedItem(item)) // Keep a subinventory display open permanently when the container is equipped
|
||||
{
|
||||
var itemContainer = item.GetComponent<ItemContainer>();
|
||||
if (itemContainer != null && itemContainer.KeepOpenWhenEquipped && !highlightedSubInventorySlots.Any(s => s.Inventory == itemContainer.Inventory))
|
||||
if (itemContainer != null &&
|
||||
itemContainer.KeepOpenWhenEquipped &&
|
||||
character.CanAccessInventory(itemContainer.Inventory) &&
|
||||
!highlightedSubInventorySlots.Any(s => s.Inventory == itemContainer.Inventory))
|
||||
{
|
||||
ShowSubInventory(new SlotReference(this, slots[i], i, false, itemContainer.Inventory), deltaTime, cam, hideSubInventories, true);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Barotrauma.Items.Components
|
||||
//openState when the vertices of the convex hull were last calculated
|
||||
private float lastConvexHullState;
|
||||
|
||||
[Serialize("1,1", false)]
|
||||
[Serialize("1,1", false, description: "The scale of the shadow-casting area of the door (relative to the actual size of the door).")]
|
||||
public Vector2 ShadowScale
|
||||
{
|
||||
get;
|
||||
@@ -102,7 +102,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
Color color = item.SpriteColor;
|
||||
if (brokenSprite == null)
|
||||
@@ -115,7 +115,7 @@ namespace Barotrauma.Items.Components
|
||||
if (stuck > 0.0f && weldedSprite != null)
|
||||
{
|
||||
Vector2 weldSpritePos = new Vector2(item.Rect.Center.X, item.Rect.Y - item.Rect.Height / 2.0f);
|
||||
if (item.Submarine != null) weldSpritePos += item.Submarine.Position;
|
||||
if (item.Submarine != null) weldSpritePos += item.Submarine.DrawPosition;
|
||||
weldSpritePos.Y = -weldSpritePos.Y;
|
||||
|
||||
weldedSprite.Draw(spriteBatch,
|
||||
|
||||
@@ -400,7 +400,7 @@ namespace Barotrauma.Items.Components
|
||||
string style = subElement.Attribute("style") == null ?
|
||||
null : subElement.GetAttributeString("style", "");
|
||||
|
||||
GuiFrame = new GUIFrame(RectTransform.Load(subElement, GUI.Canvas), style, color);
|
||||
GuiFrame = new GUIFrame(RectTransform.Load(subElement, GUI.Canvas, Anchor.Center), style, color);
|
||||
DefaultLayout = GUILayoutSettings.Load(subElement);
|
||||
break;
|
||||
case "alternativelayout":
|
||||
|
||||
@@ -33,49 +33,49 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
[Serialize("0.0,0.0", false), Editable]
|
||||
#else
|
||||
[Serialize("0.0,0.0", false)]
|
||||
[Editable]
|
||||
#endif
|
||||
[Serialize("0.0,0.0", false, description: "The position where the contained items get drawn at (offset from the upper left corner of the sprite in pixels).")]
|
||||
public Vector2 ItemPos { get; set; }
|
||||
|
||||
#if DEBUG
|
||||
[Serialize("0.0,0.0", false), Editable]
|
||||
#else
|
||||
[Serialize("0.0,0.0", false)]
|
||||
[Editable]
|
||||
#endif
|
||||
[Serialize("0.0,0.0", false, description: "The interval at which the contained items are spaced apart from each other (in pixels).")]
|
||||
public Vector2 ItemInterval { get; set; }
|
||||
[Serialize(100, false)]
|
||||
[Serialize(100, false, description: "How many items are placed in a row before starting a new row.")]
|
||||
public int ItemsPerRow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Depth at which the contained sprites are drawn. If not set, the original depth of the item sprites is used.
|
||||
/// </summary>
|
||||
[Serialize(-1.0f, false)]
|
||||
[Serialize(-1.0f, false, description: "Depth at which the contained sprites are drawn. If not set, the original depth of the item sprites is used.")]
|
||||
public float ContainedSpriteDepth { get; set; }
|
||||
|
||||
|
||||
private float itemRotation;
|
||||
[Serialize(0.0f, false)]
|
||||
[Serialize(0.0f, false, description: "The rotation in which the contained sprites are drawn (in degrees).")]
|
||||
public float ItemRotation
|
||||
{
|
||||
get { return MathHelper.ToDegrees(itemRotation); }
|
||||
set { itemRotation = MathHelper.ToRadians(value); }
|
||||
}
|
||||
|
||||
[Serialize(null, false)]
|
||||
[Serialize(null, false, description: "An optional text displayed above the item's inventory.")]
|
||||
public string UILabel { get; set; }
|
||||
|
||||
[Serialize(false, false)]
|
||||
[Serialize(false, false, description: "If enabled, the condition of this item is displayed in the indicator that would normally show the state of the contained items." +
|
||||
" May be useful for items such as ammo boxes and magazines that spawn projectiles as needed," +
|
||||
" and use the condition to determine how many projectiles can be spawned in total.")]
|
||||
public bool ShowConditionInContainedStateIndicator
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, false)]
|
||||
[Serialize(false, false, description: "Should the inventory of this item be kept open when the item is equipped by a character.")]
|
||||
public bool KeepOpenWhenEquipped { get; set; }
|
||||
[Serialize(false, false)]
|
||||
[Serialize(false, false, description: "Can the inventory of this item be moved around on the screen by the player.")]
|
||||
public bool MovableFrame { get; set; }
|
||||
|
||||
public Vector2 DrawSize
|
||||
@@ -132,13 +132,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||
{
|
||||
if (hideItems || (item.body != null && !item.body.Enabled)) { return; }
|
||||
DrawContainedItems(spriteBatch);
|
||||
DrawContainedItems(spriteBatch, itemDepth);
|
||||
}
|
||||
|
||||
public void DrawContainedItems(SpriteBatch spriteBatch)
|
||||
public void DrawContainedItems(SpriteBatch spriteBatch, float itemDepth)
|
||||
{
|
||||
Vector2 transformedItemPos = ItemPos * item.Scale;
|
||||
Vector2 transformedItemInterval = ItemInterval * item.Scale;
|
||||
@@ -199,20 +199,28 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
containedItem.body.SetTransformIgnoreContacts(containedItem.body.SimPosition, currentRotation);
|
||||
}
|
||||
|
||||
Vector2 origin = containedItem.Sprite.Origin;
|
||||
if (item.FlippedX) { origin.X = containedItem.Sprite.SourceRect.Width - origin.X; }
|
||||
if (item.FlippedY) { origin.Y = containedItem.Sprite.SourceRect.Height - origin.Y; }
|
||||
|
||||
float containedSpriteDepth = ContainedSpriteDepth < 0.0f ? containedItem.Sprite.Depth : ContainedSpriteDepth;
|
||||
containedSpriteDepth = itemDepth + (containedSpriteDepth - item.SpriteDepth) / 10000.0f;
|
||||
|
||||
containedItem.Sprite.Draw(
|
||||
spriteBatch,
|
||||
new Vector2(currentItemPos.X, -currentItemPos.Y),
|
||||
containedItem.GetSpriteColor(),
|
||||
-currentRotation,
|
||||
origin,
|
||||
- currentRotation,
|
||||
containedItem.Scale,
|
||||
spriteEffects,
|
||||
depth: ContainedSpriteDepth < 0.0f ? containedItem.Sprite.Depth : ContainedSpriteDepth);
|
||||
depth: containedSpriteDepth);
|
||||
|
||||
foreach (ItemContainer ic in containedItem.GetComponents<ItemContainer>())
|
||||
{
|
||||
if (ic.hideItems) continue;
|
||||
ic.DrawContainedItems(spriteBatch);
|
||||
ic.DrawContainedItems(spriteBatch, containedSpriteDepth);
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float[] charWidths;
|
||||
|
||||
[Serialize("0,0,0,0", true)]
|
||||
[Serialize("0,0,0,0", true, description: "The amount of padding around the text in pixels (left,top,right,bottom). ")]
|
||||
public Vector4 Padding
|
||||
{
|
||||
get { return TextBlock.Padding; }
|
||||
@@ -28,7 +28,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
private string text;
|
||||
[Serialize("", true, translationTextTag: "Label."), Editable(100)]
|
||||
[Serialize("", true, translationTextTag: "Label.", description: "The text displayed in the label."), Editable(100)]
|
||||
public string Text
|
||||
{
|
||||
get { return text; }
|
||||
@@ -54,7 +54,7 @@ namespace Barotrauma.Items.Components
|
||||
private set;
|
||||
}
|
||||
|
||||
[Editable, Serialize("0.0,0.0,0.0,1.0", true)]
|
||||
[Editable, Serialize("0,0,0,255", true, description: "The color of the text displayed on the label (R,G,B,A).")]
|
||||
public Color TextColor
|
||||
{
|
||||
get { return textColor; }
|
||||
@@ -65,7 +65,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Editable(0.0f, 10.0f), Serialize(1.0f, true)]
|
||||
[Editable(0.0f, 10.0f), Serialize(1.0f, true, description: "The scale of the text displayed on the label.")]
|
||||
public float TextScale
|
||||
{
|
||||
get { return textBlock == null ? 1.0f : textBlock.TextScale; }
|
||||
@@ -76,7 +76,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
private bool scrollable;
|
||||
[Serialize(false, true)]
|
||||
[Serialize(false, true, description: "Should the text scroll horizontally across the item if it's too long to be displayed all at once.")]
|
||||
public bool Scrollable
|
||||
{
|
||||
get { return scrollable; }
|
||||
@@ -89,7 +89,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(20.0f, true)]
|
||||
[Serialize(20.0f, true, description: "How fast the text scrolls across the item (only valid if Scrollable is set to true).")]
|
||||
public float ScrollSpeed
|
||||
{
|
||||
get;
|
||||
@@ -202,7 +202,7 @@ namespace Barotrauma.Items.Components
|
||||
TextBlock.Text = sb.ToString();
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||
{
|
||||
var drawPos = new Vector2(
|
||||
item.DrawPosition.X - item.Rect.Width / 2.0f,
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return light; }
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||
{
|
||||
if (light.LightSprite != null && (item.body == null || item.body.Enabled) && lightBrightness > 0.0f)
|
||||
{
|
||||
@@ -28,7 +28,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void FlipX(bool relativeToSub)
|
||||
{
|
||||
if (light?.LightSprite != null)
|
||||
if (light?.LightSprite != null && item.Prefab.CanSpriteFlipX)
|
||||
{
|
||||
light.LightSpriteEffect = light.LightSpriteEffect == SpriteEffects.None ?
|
||||
SpriteEffects.FlipHorizontally : SpriteEffects.None;
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace Barotrauma.Items.Components
|
||||
if (spriteIndex >= propellerSprite.FrameCount) spriteIndex = 0.0f;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
if (propellerSprite != null)
|
||||
{
|
||||
|
||||
@@ -271,11 +271,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Rectangle slotRect = outputContainer.Inventory.slots[0].Rect;
|
||||
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Rectangle(
|
||||
slotRect.X, slotRect.Y + (int)(slotRect.Height * (1.0f - progressState)),
|
||||
slotRect.Width, (int)(slotRect.Height * progressState)),
|
||||
Color.Green * 0.5f, isFilled: true);
|
||||
if (fabricatedItem != null)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch,
|
||||
new Rectangle(
|
||||
slotRect.X, slotRect.Y + (int)(slotRect.Height * (1.0f - progressState)),
|
||||
slotRect.Width, (int)(slotRect.Height * progressState)),
|
||||
Color.Green * 0.5f, isFilled: true);
|
||||
}
|
||||
|
||||
itemIcon.Draw(
|
||||
spriteBatch,
|
||||
|
||||
@@ -79,6 +79,11 @@ namespace Barotrauma.Items.Components
|
||||
displayedSubs.AddRange(item.Submarine.DockedTo);
|
||||
}
|
||||
|
||||
public override void FlipX(bool relativeToSub)
|
||||
{
|
||||
CreateHUD();
|
||||
}
|
||||
|
||||
public override void UpdateHUD(Character character, float deltaTime, Camera cam)
|
||||
{
|
||||
//recreate HUD if the subs we should display have changed
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
var btnText = warningBtn.GetChild<GUITextBlock>();
|
||||
btnText.Font = GUI.Font;
|
||||
btnText.Wrap = true;
|
||||
btnText.Wrap = false;
|
||||
btnText.SetTextPos();
|
||||
warningButtons.Add(warningTexts[i], warningBtn);
|
||||
}
|
||||
|
||||
@@ -27,12 +27,16 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private GUITickBox directionalTickBox;
|
||||
private GUIScrollBar directionalSlider;
|
||||
private Vector2? pingDragDirection = null;
|
||||
|
||||
private GUILayoutGroup activeControlsContainer;
|
||||
private GUIFrame controlContainer;
|
||||
|
||||
private GUICustomComponent sonarView;
|
||||
|
||||
private Sprite directionalPingBackground;
|
||||
private Sprite[] directionalPingButton;
|
||||
|
||||
private float displayBorderSize;
|
||||
|
||||
private List<SonarBlip> sonarBlips;
|
||||
@@ -149,14 +153,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
showDirectionalIndicatorTimer = 1.0f;
|
||||
float pingAngle = MathHelper.Lerp(0.0f, MathHelper.TwoPi, scroll);
|
||||
pingDirection = new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle));
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
unsentChanges = true;
|
||||
correctionTimer = CorrectionDelay;
|
||||
}
|
||||
SetPingDirection(new Vector2((float)Math.Cos(pingAngle), (float)Math.Sin(pingAngle)));
|
||||
return true;
|
||||
}
|
||||
},
|
||||
Range = new Vector2(0,MathHelper.TwoPi)
|
||||
};
|
||||
|
||||
signalWarningText = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.15f), paddedControlContainer.RectTransform), "", Color.Orange, textAlignment: Alignment.Center);
|
||||
@@ -178,6 +178,14 @@ namespace Barotrauma.Items.Components
|
||||
case "directionalpingcircle":
|
||||
directionalPingCircle = new Sprite(subElement);
|
||||
break;
|
||||
case "directionalpingbackground":
|
||||
directionalPingBackground = new Sprite(subElement);
|
||||
break;
|
||||
case "directionalpingbutton":
|
||||
if (directionalPingButton == null) { directionalPingButton = new Sprite[3]; }
|
||||
int index = subElement.GetAttributeInt("index", 0);
|
||||
directionalPingButton[index] = new Sprite(subElement);
|
||||
break;
|
||||
case "screenoverlay":
|
||||
screenOverlay = new Sprite(subElement);
|
||||
break;
|
||||
@@ -206,6 +214,16 @@ namespace Barotrauma.Items.Components
|
||||
controlContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0);
|
||||
}
|
||||
|
||||
private void SetPingDirection(Vector2 direction)
|
||||
{
|
||||
pingDirection = direction;
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
unsentChanges = true;
|
||||
correctionTimer = CorrectionDelay;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
zoomSlider.BarScroll = MathUtils.InverseLerp(MinZoom, MaxZoom, zoom);
|
||||
@@ -352,6 +370,43 @@ namespace Barotrauma.Items.Components
|
||||
prevDockingDist = float.MaxValue;
|
||||
}
|
||||
|
||||
if (steering != null && directionalPingButton != null)
|
||||
{
|
||||
steering.SteerRadius = useDirectionalPing && pingDragDirection != null ?
|
||||
-1.0f :
|
||||
PlayerInput.LeftButtonDown() || !PlayerInput.LeftButtonHeld() ?
|
||||
(float?)((sonarView.Rect.Width / 2) - (directionalPingButton[0].size.X * sonarView.Rect.Width / screenBackground.size.X)) :
|
||||
null;
|
||||
}
|
||||
|
||||
if (useDirectionalPing && PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
if ((MouseInDirectionalPingRing(sonarView.Rect, false) && PlayerInput.LeftButtonDown()) || pingDragDirection != null)
|
||||
{
|
||||
Vector2 newDragDir = Vector2.Normalize(PlayerInput.MousePosition - sonarView.Rect.Center.ToVector2());
|
||||
if (pingDragDirection == null && !MouseInDirectionalPingRing(sonarView.Rect, true))
|
||||
{
|
||||
directionalSlider.BarScrollValue = MathUtils.WrapAngleTwoPi(MathUtils.VectorToAngle(newDragDir));
|
||||
directionalSlider.OnMoved(directionalSlider, directionalSlider.BarScroll);
|
||||
}
|
||||
else if (pingDragDirection != null)
|
||||
{
|
||||
float newAngle = MathUtils.VectorToAngle(newDragDir);
|
||||
float oldAngle = MathUtils.VectorToAngle(pingDragDirection.Value);
|
||||
float pingAngle = MathUtils.VectorToAngle(pingDirection);
|
||||
pingAngle = MathUtils.WrapAngleTwoPi(pingAngle + MathUtils.GetShortestAngle(oldAngle, newAngle));
|
||||
directionalSlider.BarScrollValue = pingAngle;
|
||||
directionalSlider.OnMoved(directionalSlider, directionalSlider.BarScroll);
|
||||
}
|
||||
|
||||
pingDragDirection = newDragDir;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pingDragDirection = null;
|
||||
}
|
||||
|
||||
for (var pingIndex = 0; pingIndex < activePingsCount; ++pingIndex)
|
||||
{
|
||||
var activePing = activePings[pingIndex];
|
||||
@@ -391,6 +446,28 @@ namespace Barotrauma.Items.Components
|
||||
prevPassivePingRadius = passivePingRadius;
|
||||
}
|
||||
|
||||
private bool MouseInDirectionalPingRing(Rectangle rect, bool onButton)
|
||||
{
|
||||
if (!useDirectionalPing || directionalPingButton == null) { return false; }
|
||||
|
||||
float endRadius = rect.Width / 2.0f;
|
||||
float startRadius = endRadius - directionalPingButton[0].size.X * rect.Width / screenBackground.size.X;
|
||||
|
||||
Vector2 center = rect.Center.ToVector2();
|
||||
|
||||
float dist = Vector2.DistanceSquared(PlayerInput.MousePosition,center);
|
||||
|
||||
bool retVal = (dist >= startRadius*startRadius) && (dist < endRadius*endRadius);
|
||||
if (onButton)
|
||||
{
|
||||
float pingAngle = MathUtils.VectorToAngle(pingDirection);
|
||||
float mouseAngle = MathUtils.VectorToAngle(Vector2.Normalize(PlayerInput.MousePosition - center));
|
||||
retVal &= Math.Abs(MathUtils.GetShortestAngle(mouseAngle, pingAngle)) < MathHelper.ToRadians(DirectionalPingSector * 0.5f);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private void DrawSonar(SpriteBatch spriteBatch, Rectangle rect)
|
||||
{
|
||||
displayBorderSize = 0.2f;
|
||||
@@ -403,6 +480,24 @@ namespace Barotrauma.Items.Components
|
||||
screenBackground.Draw(spriteBatch, center, 0.0f, rect.Width / screenBackground.size.X);
|
||||
}
|
||||
|
||||
if (useDirectionalPing)
|
||||
{
|
||||
directionalPingBackground?.Draw(spriteBatch, center, 0.0f, rect.Width / directionalPingBackground.size.X);
|
||||
if (directionalPingButton != null)
|
||||
{
|
||||
int buttonSprIndex = 0;
|
||||
if (pingDragDirection != null)
|
||||
{
|
||||
buttonSprIndex = 2;
|
||||
}
|
||||
else if (MouseInDirectionalPingRing(rect, true))
|
||||
{
|
||||
buttonSprIndex = 1;
|
||||
}
|
||||
directionalPingButton[buttonSprIndex]?.Draw(spriteBatch, center, MathUtils.VectorToAngle(pingDirection), rect.Width / directionalPingBackground.size.X);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentMode == Mode.Active && currentPingIndex != -1)
|
||||
{
|
||||
var activePing = activePings[currentPingIndex];
|
||||
|
||||
@@ -47,6 +47,10 @@ namespace Barotrauma.Items.Components
|
||||
private Sprite maintainPosIndicator, maintainPosOriginIndicator;
|
||||
private Sprite steeringIndicator;
|
||||
|
||||
private List<DockingPort> connectedPorts = new List<DockingPort>();
|
||||
private float checkConnectedPortsTimer;
|
||||
private const float CheckConnectedPortsInterval = 1.0f;
|
||||
|
||||
private Vector2 keyboardInput = Vector2.Zero;
|
||||
private float inputCumulation;
|
||||
|
||||
@@ -86,6 +90,19 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
} = true;
|
||||
|
||||
private float steerRadius;
|
||||
public float? SteerRadius
|
||||
{
|
||||
get
|
||||
{
|
||||
return steerRadius;
|
||||
}
|
||||
set
|
||||
{
|
||||
steerRadius = value ?? (steerArea.Rect.Width / 2);
|
||||
}
|
||||
}
|
||||
|
||||
public List<DockingPort> DockingSources = new List<DockingPort>();
|
||||
public DockingPort ActiveDockingSource, DockingTarget;
|
||||
|
||||
@@ -317,7 +334,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
{
|
||||
item.SendSignal(0, "1", "toggle_docking", sender: Character.Controlled);
|
||||
item.SendSignal(0, "1", "toggle_docking", sender: null);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -384,6 +401,8 @@ namespace Barotrauma.Items.Components
|
||||
statusContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0);
|
||||
steerArea.RectTransform.NonScaledSize = new Point(viewSize);
|
||||
dockingContainer.RectTransform.AbsoluteOffset = new Point((int)(viewSize * 0.9f), 0);
|
||||
|
||||
steerRadius = steerArea.Rect.Width / 2;
|
||||
}
|
||||
|
||||
private void FindConnectedDockingPort()
|
||||
@@ -661,7 +680,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
pressureWarningText.Visible = item.Submarine != null && item.Submarine.AtDamageDepth && Timing.TotalTime % 1.0f < 0.5f;
|
||||
|
||||
if (Vector2.Distance(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerArea.Rect.Width / 2)
|
||||
if (Vector2.DistanceSquared(PlayerInput.MousePosition, steerArea.Rect.Center.ToVector2()) < steerRadius * steerRadius)
|
||||
{
|
||||
if (PlayerInput.LeftButtonHeld())
|
||||
{
|
||||
@@ -735,10 +754,21 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
if (!UseAutoDocking) { return; }
|
||||
|
||||
if (checkConnectedPortsTimer <= 0.0f)
|
||||
{
|
||||
Connection dockingConnection = item.Connections?.FirstOrDefault(c => c.Name == "toggle_docking");
|
||||
if (dockingConnection != null)
|
||||
{
|
||||
connectedPorts = item.GetConnectedComponentsRecursive<DockingPort>(dockingConnection);
|
||||
}
|
||||
checkConnectedPortsTimer = CheckConnectedPortsInterval;
|
||||
}
|
||||
|
||||
float closestDist = DockingAssistThreshold * DockingAssistThreshold;
|
||||
DockingModeEnabled = false;
|
||||
foreach (DockingPort sourcePort in DockingPort.List)
|
||||
|
||||
foreach (DockingPort sourcePort in connectedPorts)
|
||||
{
|
||||
if (sourcePort.Docked || sourcePort.Item.Submarine == null) { continue; }
|
||||
if (sourcePort.Item.Submarine != controlledSub) { continue; }
|
||||
@@ -826,6 +856,7 @@ namespace Barotrauma.Items.Components
|
||||
int msgStartPos = msg.BitPosition;
|
||||
|
||||
bool autoPilot = msg.ReadBoolean();
|
||||
bool dockingButtonClicked = msg.ReadBoolean();
|
||||
Vector2 newSteeringInput = steeringInput;
|
||||
Vector2 newTargetVelocity = targetVelocity;
|
||||
float newSteeringAdjustSpeed = steeringAdjustSpeed;
|
||||
@@ -833,6 +864,11 @@ namespace Barotrauma.Items.Components
|
||||
Vector2? newPosToMaintain = null;
|
||||
bool headingToStart = false;
|
||||
|
||||
if (dockingButtonClicked)
|
||||
{
|
||||
item.SendSignal(0, "1", "toggle_docking", sender: null);
|
||||
}
|
||||
|
||||
if (autoPilot)
|
||||
{
|
||||
maintainPos = msg.ReadBoolean();
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Barotrauma.Items.Components
|
||||
chargeIndicator.Color = ToolBox.GradientLerp(chargeRatio, Color.Red, Color.Orange, Color.Green);
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||
{
|
||||
if (indicatorSize.X <= 1.0f || indicatorSize.Y <= 1.0f) return;
|
||||
|
||||
@@ -143,7 +143,10 @@ namespace Barotrauma.Items.Components
|
||||
float rechargeRate = msg.ReadRangedInteger(0, 10) / 10.0f;
|
||||
RechargeSpeed = rechargeRate * MaxRechargeSpeed;
|
||||
#if CLIENT
|
||||
rechargeSpeedSlider.BarScroll = rechargeRate;
|
||||
if (rechargeSpeedSlider != null)
|
||||
{
|
||||
rechargeSpeedSlider.BarScroll = rechargeRate;
|
||||
}
|
||||
#endif
|
||||
Charge = msg.ReadRangedSingle(0.0f, 1.0f, 8) * capacity;
|
||||
}
|
||||
|
||||
@@ -16,21 +16,17 @@ namespace Barotrauma.Items.Components
|
||||
: IDrawableComponent
|
||||
#endif
|
||||
{
|
||||
public ParticleEmitter ParticleEmitter
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
#if DEBUG
|
||||
public Vector2 DrawSize
|
||||
{
|
||||
get { return GameMain.DebugDraw ? Vector2.One * Range : Vector2.Zero; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private List<ParticleEmitter> ParticleEmitterHitStructure = new List<ParticleEmitter>();
|
||||
private List<ParticleEmitter> ParticleEmitterHitCharacter = new List<ParticleEmitter>();
|
||||
private List<Pair<RelatedItem, ParticleEmitter>> ParticleEmitterHitItem = new List<Pair<RelatedItem, ParticleEmitter>>();
|
||||
private List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
private List<ParticleEmitter> particleEmitterHitStructure = new List<ParticleEmitter>();
|
||||
private List<ParticleEmitter> particleEmitterHitCharacter = new List<ParticleEmitter>();
|
||||
private List<Pair<RelatedItem, ParticleEmitter>> particleEmitterHitItem = new List<Pair<RelatedItem, ParticleEmitter>>();
|
||||
|
||||
private float prevProgressBarState;
|
||||
|
||||
@@ -41,7 +37,7 @@ namespace Barotrauma.Items.Components
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "particleemitter":
|
||||
ParticleEmitter = new ParticleEmitter(subElement);
|
||||
particleEmitters.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
case "particleemitterhititem":
|
||||
string[] identifiers = subElement.GetAttributeStringArray("identifiers", new string[0]);
|
||||
@@ -49,16 +45,16 @@ namespace Barotrauma.Items.Components
|
||||
string[] excludedIdentifiers = subElement.GetAttributeStringArray("excludedidentifiers", new string[0]);
|
||||
if (excludedIdentifiers.Length == 0) excludedIdentifiers = subElement.GetAttributeStringArray("excludedidentifier", new string[0]);
|
||||
|
||||
ParticleEmitterHitItem.Add(
|
||||
particleEmitterHitItem.Add(
|
||||
new Pair<RelatedItem, ParticleEmitter>(
|
||||
new RelatedItem(identifiers, excludedIdentifiers),
|
||||
new ParticleEmitter(subElement)));
|
||||
break;
|
||||
case "particleemitterhitstructure":
|
||||
ParticleEmitterHitStructure.Add(new ParticleEmitter(subElement));
|
||||
particleEmitterHitStructure.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
case "particleemitterhitcharacter":
|
||||
ParticleEmitterHitCharacter.Add(new ParticleEmitter(subElement));
|
||||
particleEmitterHitCharacter.Add(new ParticleEmitter(subElement));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -67,12 +63,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void UseProjSpecific(float deltaTime, Vector2 raystart)
|
||||
{
|
||||
if (ParticleEmitter != null)
|
||||
foreach (ParticleEmitter particleEmitter in particleEmitters)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
ParticleEmitter.Emit(
|
||||
particleEmitter.Emit(
|
||||
deltaTime, ConvertUnits.ToDisplayUnits(raystart),
|
||||
item.CurrentHull, particleAngle, ParticleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0);
|
||||
item.CurrentHull, particleAngle, particleEmitter.Prefab.CopyEntityAngle ? -particleAngle : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +90,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetStructure.Submarine != null) particlePos += targetStructure.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitStructure)
|
||||
foreach (var emitter in particleEmitterHitStructure)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||
@@ -105,7 +101,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetCharacter.Submarine != null) particlePos += targetCharacter.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitCharacter)
|
||||
foreach (var emitter in particleEmitterHitCharacter)
|
||||
{
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
emitter.Emit(deltaTime, particlePos, item.CurrentHull, particleAngle + MathHelper.Pi, -particleAngle + MathHelper.Pi);
|
||||
@@ -133,7 +129,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
Vector2 particlePos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetItem.Submarine != null) particlePos += targetItem.Submarine.DrawPosition;
|
||||
foreach (var emitter in ParticleEmitterHitItem)
|
||||
foreach (var emitter in particleEmitterHitItem)
|
||||
{
|
||||
if (!emitter.First.MatchesItem(targetItem)) continue;
|
||||
float particleAngle = item.body.Rotation + ((item.body.Dir > 0.0f) ? 0.0f : MathHelper.Pi);
|
||||
@@ -141,7 +137,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
if (GameMain.DebugDraw && IsActive)
|
||||
{
|
||||
|
||||
@@ -10,16 +10,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Repairable : ItemComponent, IDrawableComponent
|
||||
{
|
||||
public GUIButton RepairButton
|
||||
{
|
||||
get { return repairButton; }
|
||||
}
|
||||
private GUIButton repairButton;
|
||||
public GUIButton SabotageButton
|
||||
{
|
||||
get { return sabotageButton; }
|
||||
}
|
||||
private GUIButton sabotageButton;
|
||||
public GUIButton RepairButton { get; private set; }
|
||||
|
||||
public GUIButton SabotageButton { get; private set; }
|
||||
|
||||
private GUIProgressBar progressBar;
|
||||
|
||||
private List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
@@ -33,7 +27,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private FixActions requestStartFixAction;
|
||||
|
||||
[Serialize("", false)]
|
||||
[Serialize("", false, description: "An optional description of the needed repairs displayed in the repair interface.")]
|
||||
public string Description
|
||||
{
|
||||
get;
|
||||
@@ -83,7 +77,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
repairButtonText = TextManager.Get("RepairButton");
|
||||
repairingText = TextManager.Get("Repairing");
|
||||
repairButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.TopCenter), repairButtonText)
|
||||
RepairButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.TopCenter), repairButtonText)
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
@@ -94,7 +88,7 @@ namespace Barotrauma.Items.Components
|
||||
};
|
||||
sabotageButtonText = TextManager.Get("SabotageButton");
|
||||
sabotagingText = TextManager.Get("Sabotaging");
|
||||
sabotageButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.BottomCenter), sabotageButtonText)
|
||||
SabotageButton = new GUIButton(new RectTransform(new Vector2(0.8f, 0.15f), paddedFrame.RectTransform, Anchor.BottomCenter), sabotageButtonText)
|
||||
{
|
||||
OnClicked = (btn, obj) =>
|
||||
{
|
||||
@@ -165,14 +159,14 @@ namespace Barotrauma.Items.Components
|
||||
progressBar.BarSize = item.Condition / item.MaxCondition;
|
||||
progressBar.Color = ToolBox.GradientLerp(progressBar.BarSize, Color.Red, Color.Orange, Color.Green);
|
||||
|
||||
repairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && item.ConditionPercentage <= ShowRepairUIThreshold;
|
||||
repairButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Repair) ?
|
||||
RepairButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Repair)) && item.ConditionPercentage <= ShowRepairUIThreshold;
|
||||
RepairButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Repair) ?
|
||||
repairButtonText :
|
||||
repairingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
|
||||
sabotageButton.Visible = character.IsTraitor;
|
||||
sabotageButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Sabotage)) && character.IsTraitor && item.ConditionPercentage > MinSabotageCondition;
|
||||
sabotageButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Sabotage || !character.IsTraitor) ?
|
||||
SabotageButton.Visible = character.IsTraitor;
|
||||
SabotageButton.Enabled = (currentFixerAction == FixActions.None || (CurrentFixer == character && currentFixerAction != FixActions.Sabotage)) && character.IsTraitor && item.ConditionPercentage > MinSabotageCondition;
|
||||
SabotageButton.Text = (currentFixerAction == FixActions.None || CurrentFixer != character || currentFixerAction != FixActions.Sabotage || !character.IsTraitor) ?
|
||||
sabotageButtonText :
|
||||
sabotagingText + new string('.', ((int)(Timing.TotalTime * 2.0f) % 3) + 1);
|
||||
|
||||
@@ -193,7 +187,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
if (GameMain.DebugDraw && Character.Controlled?.FocusedItem == item)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return new Vector2(rangeX, rangeY) * 2.0f; }
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
if (!editing || !MapEntity.SelectedList.Contains(item)) return;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return new Vector2(range * 2); }
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
if (!editing || !MapEntity.SelectedList.Contains(item)) return;
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return sectionExtents; }
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
if (sections.Count == 0 && !IsActive || Hidden)
|
||||
{
|
||||
@@ -154,6 +154,18 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public static void UpdateEditing(List<Wire> wires)
|
||||
{
|
||||
Wire equippedWire =
|
||||
Character.Controlled?.SelectedItems[0]?.GetComponent<Wire>() ??
|
||||
Character.Controlled?.SelectedItems[1]?.GetComponent<Wire>();
|
||||
if (equippedWire != null)
|
||||
{
|
||||
if (PlayerInput.LeftButtonClicked() && Character.Controlled.SelectedConstruction == null)
|
||||
{
|
||||
equippedWire.Use(1.0f, Character.Controlled);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//dragging a node of some wire
|
||||
if (draggingWire != null)
|
||||
{
|
||||
|
||||
@@ -33,14 +33,14 @@ namespace Barotrauma.Items.Components
|
||||
TextManager.Get("NotBreathing")
|
||||
};
|
||||
|
||||
[Serialize(500.0f, false)]
|
||||
[Serialize(500.0f, false, description: "How close to a target the user must be to see their health data (in pixels).")]
|
||||
public float Range
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(50.0f, false)]
|
||||
[Serialize(50.0f, false, description: "The range within which the health info texts fades out.")]
|
||||
public float FadeOutRange
|
||||
{
|
||||
get;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private Vector2 crosshairPos, crosshairPointerPos;
|
||||
|
||||
private Dictionary<string, Widget> widgets = new Dictionary<string, Widget>();
|
||||
private readonly Dictionary<string, Widget> widgets = new Dictionary<string, Widget>();
|
||||
private float prevAngle;
|
||||
|
||||
private bool flashLowPower;
|
||||
@@ -33,30 +33,30 @@ namespace Barotrauma.Items.Components
|
||||
private float flashTimer;
|
||||
private float flashLength = 1;
|
||||
|
||||
private List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||
|
||||
[Editable, Serialize("0.0,0.0,0.0,0.0", true)]
|
||||
[Editable, Serialize("0,0,0,0", true, description: "Optional screen tint color when the item is being operated (R,G,B,A).")]
|
||||
public Color HudTint
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(false, false)]
|
||||
[Serialize(false, false, description: "Should the charge of the connected batteries/supercapacitors be shown at the top of the screen when operating the item.")]
|
||||
public bool ShowChargeIndicator
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(false, false)]
|
||||
[Serialize(false, false, description: "Should the available ammunition be shown at the top of the screen when operating the item.")]
|
||||
public bool ShowProjectileIndicator
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
[Serialize(0.0f, false, description: "How far the barrel \"recoils back\" when the turret is fired (in pixels).")]
|
||||
public float RecoilDistance
|
||||
{
|
||||
get;
|
||||
@@ -240,7 +240,7 @@ namespace Barotrauma.Items.Components
|
||||
crosshairPointerPos = PlayerInput.MousePosition;
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||
{
|
||||
Vector2 drawPos = new Vector2(item.Rect.X + transformedBarrelPos.X, item.Rect.Y - transformedBarrelPos.Y);
|
||||
if (item.Submarine != null) drawPos += item.Submarine.DrawPosition;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return Vector2.Zero; }
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth = -1)
|
||||
{
|
||||
if (dockingState == 0.0f) return;
|
||||
|
||||
@@ -105,5 +105,56 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
||||
{
|
||||
bool isDocked = msg.ReadBoolean();
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (hulls[i] == null) continue;
|
||||
item.linkedTo.Remove(hulls[i]);
|
||||
hulls[i].Remove();
|
||||
hulls[i] = null;
|
||||
}
|
||||
|
||||
if (gap != null)
|
||||
{
|
||||
item.linkedTo.Remove(gap);
|
||||
gap.Remove();
|
||||
gap = null;
|
||||
}
|
||||
|
||||
if (isDocked)
|
||||
{
|
||||
ushort dockingTargetID = msg.ReadUInt16();
|
||||
|
||||
bool isLocked = msg.ReadBoolean();
|
||||
|
||||
Entity targetEntity = Entity.FindEntityByID(dockingTargetID);
|
||||
if (targetEntity == null || !(targetEntity is Item))
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid docking port network event (can't dock to " + targetEntity?.ToString() ?? "null" + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
DockingTarget = (targetEntity as Item).GetComponent<DockingPort>();
|
||||
if (DockingTarget == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Invalid docking port network event (" + targetEntity + " doesn't have a docking port component)");
|
||||
return;
|
||||
}
|
||||
|
||||
Dock(DockingTarget);
|
||||
|
||||
if (isLocked)
|
||||
{
|
||||
Lock(isNetworkMessage: true, forcePosition: true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Undock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,14 @@ namespace Barotrauma
|
||||
|
||||
public static SlotReference SelectedSlot
|
||||
{
|
||||
get { return selectedSlot; }
|
||||
get
|
||||
{
|
||||
if (selectedSlot?.ParentInventory?.Owner == null || selectedSlot.ParentInventory.Owner.Removed)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return selectedSlot;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void CreateSlots()
|
||||
@@ -430,6 +437,8 @@ namespace Barotrauma
|
||||
|
||||
if (canMove)
|
||||
{
|
||||
subInventory.HideTimer = 1.0f;
|
||||
subInventory.OpenState = 1.0f;
|
||||
if (subInventory.movableFrameRect.Contains(PlayerInput.MousePosition) && PlayerInput.RightButtonClicked())
|
||||
{
|
||||
container.Inventory.savedPosition = container.Inventory.originalPos;
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Barotrauma
|
||||
public float LastImpactSoundTime;
|
||||
public const float ImpactSoundInterval = 0.2f;
|
||||
|
||||
private bool editingHUDRefreshPending;
|
||||
private float editingHUDRefreshTimer;
|
||||
|
||||
class SpriteState
|
||||
{
|
||||
public float RotationState;
|
||||
@@ -33,7 +36,7 @@ namespace Barotrauma
|
||||
public bool IsActive = true;
|
||||
}
|
||||
|
||||
private Dictionary<ItemPrefab.DecorativeSprite, SpriteState> spriteAnimState = new Dictionary<ItemPrefab.DecorativeSprite, SpriteState>();
|
||||
private Dictionary<DecorativeSprite, SpriteState> spriteAnimState = new Dictionary<DecorativeSprite, SpriteState>();
|
||||
|
||||
private Sprite activeSprite;
|
||||
public override Sprite Sprite
|
||||
@@ -128,11 +131,13 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
foreach (BrokenItemSprite brokenSprite in Prefab.BrokenSprites)
|
||||
for (int i = 0; i < Prefab.BrokenSprites.Count;i++)
|
||||
{
|
||||
if (condition <= brokenSprite.MaxCondition)
|
||||
float minCondition = i > 0 ? Prefab.BrokenSprites[i - i].MaxCondition : 0.0f;
|
||||
if (condition <= minCondition ||
|
||||
condition <= Prefab.BrokenSprites[i].MaxCondition && !Prefab.BrokenSprites[i].FadeIn)
|
||||
{
|
||||
activeSprite = brokenSprite.Sprite;
|
||||
activeSprite = Prefab.BrokenSprites[i].Sprite;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -211,18 +216,18 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
float depth = GetDrawDepth();
|
||||
if (activeSprite != null)
|
||||
{
|
||||
SpriteEffects oldEffects = activeSprite.effects;
|
||||
activeSprite.effects ^= SpriteEffects;
|
||||
SpriteEffects oldBrokenSpriteEffects = SpriteEffects.None;
|
||||
if (fadeInBrokenSprite != null)
|
||||
if (fadeInBrokenSprite != null && fadeInBrokenSprite.Sprite != activeSprite)
|
||||
{
|
||||
oldBrokenSpriteEffects = fadeInBrokenSprite.Sprite.effects;
|
||||
fadeInBrokenSprite.Sprite.effects ^= SpriteEffects;
|
||||
}
|
||||
|
||||
float depth = GetDrawDepth();
|
||||
if (body == null)
|
||||
{
|
||||
bool flipHorizontal = (SpriteEffects & SpriteEffects.FlipHorizontally) != 0;
|
||||
@@ -304,9 +309,9 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
activeSprite.effects = oldEffects;
|
||||
if (fadeInBrokenSprite != null)
|
||||
if (fadeInBrokenSprite != null && fadeInBrokenSprite.Sprite != activeSprite)
|
||||
{
|
||||
fadeInBrokenSprite.Sprite.effects = oldEffects;
|
||||
fadeInBrokenSprite.Sprite.effects = oldBrokenSpriteEffects;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,7 +319,7 @@ namespace Barotrauma
|
||||
//causing them to be removed from the list
|
||||
for (int i = drawableComponents.Count - 1; i >= 0; i--)
|
||||
{
|
||||
drawableComponents[i].Draw(spriteBatch, editing);
|
||||
drawableComponents[i].Draw(spriteBatch, editing, depth);
|
||||
}
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
@@ -437,21 +442,23 @@ namespace Barotrauma
|
||||
|
||||
public override void UpdateEditing(Camera cam)
|
||||
{
|
||||
if (editingHUD == null || editingHUD.UserData as Item != this)
|
||||
if (editingHUD == null || editingHUD.UserData as Item != this ||
|
||||
(editingHUDRefreshPending && editingHUDRefreshTimer <= 0.0f))
|
||||
{
|
||||
editingHUD = CreateEditingHUD(Screen.Selected != GameMain.SubEditorScreen);
|
||||
editingHUDRefreshTimer = 1.0f;
|
||||
}
|
||||
|
||||
if (Screen.Selected != GameMain.SubEditorScreen) return;
|
||||
if (Screen.Selected != GameMain.SubEditorScreen) { return; }
|
||||
|
||||
if (Character.Controlled == null) activeHUDs.Clear();
|
||||
if (Character.Controlled == null) { activeHUDs.Clear(); }
|
||||
|
||||
if (!Linkable) return;
|
||||
if (!Linkable) { return; }
|
||||
|
||||
if (!PlayerInput.KeyDown(Keys.Space)) return;
|
||||
if (!PlayerInput.KeyDown(Keys.Space)) { return; }
|
||||
bool lClick = PlayerInput.LeftButtonClicked();
|
||||
bool rClick = PlayerInput.RightButtonClicked();
|
||||
if (!lClick && !rClick) return;
|
||||
if (!lClick && !rClick) { return; }
|
||||
|
||||
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||
var otherEntity = mapEntityList.FirstOrDefault(e => e != this && e.IsHighlighted && e.IsMouseOn(position));
|
||||
@@ -472,6 +479,8 @@ namespace Barotrauma
|
||||
|
||||
public GUIComponent CreateEditingHUD(bool inGame = false)
|
||||
{
|
||||
editingHUDRefreshPending = false;
|
||||
|
||||
int heightScaled = (int)(20 * GUI.Scale);
|
||||
editingHUD = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.25f), GUI.Canvas, Anchor.CenterRight) { MinSize = new Point(400, 0) }) { UserData = this };
|
||||
GUIListBox listBox = new GUIListBox(new RectTransform(new Vector2(0.95f, 0.8f), editingHUD.RectTransform, Anchor.Center), style: null)
|
||||
@@ -672,6 +681,13 @@ namespace Barotrauma
|
||||
editingHUDCreated = editingHUD != null && editingHUD != prevEditingHUD;
|
||||
}
|
||||
|
||||
if (editingHUD == null ||
|
||||
!(GUI.KeyboardDispatcher.Subscriber is GUITextBox textBox) ||
|
||||
!editingHUD.IsParentOf(textBox))
|
||||
{
|
||||
editingHUDRefreshTimer -= deltaTime;
|
||||
}
|
||||
|
||||
List<ItemComponent> prevActiveHUDs = new List<ItemComponent>(activeHUDs);
|
||||
List<ItemComponent> activeComponents = new List<ItemComponent>(components);
|
||||
foreach (MapEntity entity in linkedTo)
|
||||
@@ -916,6 +932,7 @@ namespace Barotrauma
|
||||
break;
|
||||
case NetEntityEvent.Type.ChangeProperty:
|
||||
ReadPropertyChange(msg, false);
|
||||
editingHUDRefreshPending = true;
|
||||
break;
|
||||
case NetEntityEvent.Type.Invalid:
|
||||
break;
|
||||
@@ -954,6 +971,7 @@ namespace Barotrauma
|
||||
break;
|
||||
case NetEntityEvent.Type.ChangeProperty:
|
||||
WritePropertyChange(msg, extraData, true);
|
||||
editingHUDRefreshTimer = 1.0f;
|
||||
break;
|
||||
case NetEntityEvent.Type.Combine:
|
||||
UInt16 combineTargetID = (UInt16)extraData[1];
|
||||
@@ -969,6 +987,7 @@ namespace Barotrauma
|
||||
|
||||
if (parentInventory != null || body == null || !body.Enabled || Removed)
|
||||
{
|
||||
positionBuffer.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,138 +47,6 @@ namespace Barotrauma
|
||||
|
||||
partial class ItemPrefab : MapEntityPrefab
|
||||
{
|
||||
public class DecorativeSprite
|
||||
{
|
||||
public Sprite Sprite { get; private set; }
|
||||
|
||||
public enum AnimationType
|
||||
{
|
||||
None,
|
||||
Sine,
|
||||
Noise
|
||||
}
|
||||
|
||||
[Serialize("0,0", false)]
|
||||
public Vector2 Offset { get; private set; }
|
||||
|
||||
[Serialize(AnimationType.None, false)]
|
||||
public AnimationType OffsetAnim { get; private set; }
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float OffsetAnimSpeed { get; private set; }
|
||||
|
||||
private float rotationSpeedRadians;
|
||||
[Serialize(0.0f, false)]
|
||||
public float RotationSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
return MathHelper.ToDegrees(rotationSpeedRadians);
|
||||
}
|
||||
private set
|
||||
{
|
||||
rotationSpeedRadians = MathHelper.ToRadians(value);
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float Rotation { get; private set; }
|
||||
|
||||
[Serialize(AnimationType.None, false)]
|
||||
public AnimationType RotationAnim { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If > 0, only one sprite of the same group is used (chosen randomly)
|
||||
/// </summary>
|
||||
[Serialize(0, false)]
|
||||
public int RandomGroupID { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The sprite is only drawn if these conditions are fulfilled
|
||||
/// </summary>
|
||||
public List<PropertyConditional> IsActiveConditionals { get; private set; } = new List<PropertyConditional>();
|
||||
/// <summary>
|
||||
/// The sprite is only animated if these conditions are fulfilled
|
||||
/// </summary>
|
||||
public List<PropertyConditional> AnimationConditionals { get; private set; } = new List<PropertyConditional>();
|
||||
|
||||
public DecorativeSprite(XElement element, string path = "", bool lazyLoad = false)
|
||||
{
|
||||
Sprite = new Sprite(element, path, lazyLoad: lazyLoad);
|
||||
SerializableProperty.DeserializeProperties(this, element);
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
List<PropertyConditional> conditionalList = null;
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "conditional":
|
||||
case "isactiveconditional":
|
||||
conditionalList = IsActiveConditionals;
|
||||
break;
|
||||
case "animationconditional":
|
||||
conditionalList = AnimationConditionals;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
foreach (XAttribute attribute in subElement.Attributes())
|
||||
{
|
||||
if (attribute.Name.ToString().ToLowerInvariant() == "targetitemcomponent") { continue; }
|
||||
conditionalList.Add(new PropertyConditional(attribute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vector2 GetOffset(ref float offsetState)
|
||||
{
|
||||
if (OffsetAnimSpeed <= 0.0f)
|
||||
{
|
||||
return Offset;
|
||||
}
|
||||
switch (OffsetAnim)
|
||||
{
|
||||
case AnimationType.Sine:
|
||||
offsetState = offsetState % (MathHelper.TwoPi / OffsetAnimSpeed);
|
||||
return Offset * (float)Math.Sin(offsetState * OffsetAnimSpeed);
|
||||
case AnimationType.Noise:
|
||||
offsetState = offsetState % (1.0f / (OffsetAnimSpeed * 0.1f));
|
||||
|
||||
float t = offsetState * 0.1f * OffsetAnimSpeed;
|
||||
return new Vector2(
|
||||
Offset.X * (PerlinNoise.GetPerlin(t, t) - 0.5f),
|
||||
Offset.Y * (PerlinNoise.GetPerlin(t + 0.5f, t + 0.5f) - 0.5f));
|
||||
default:
|
||||
return Offset;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetRotation(ref float rotationState)
|
||||
{
|
||||
if (rotationSpeedRadians <= 0.0f)
|
||||
{
|
||||
return Rotation;
|
||||
}
|
||||
switch (OffsetAnim)
|
||||
{
|
||||
case AnimationType.Sine:
|
||||
rotationState = rotationState % (MathHelper.TwoPi / rotationSpeedRadians);
|
||||
return Rotation * (float)Math.Sin(rotationState * rotationSpeedRadians);
|
||||
case AnimationType.Noise:
|
||||
rotationState = rotationState % (1.0f / rotationSpeedRadians);
|
||||
return Rotation * PerlinNoise.GetPerlin(rotationState * rotationSpeedRadians, rotationState * rotationSpeedRadians);
|
||||
default:
|
||||
return rotationState * rotationSpeedRadians;
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
Sprite?.Remove();
|
||||
Sprite = null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<BrokenItemSprite> BrokenSprites = new List<BrokenItemSprite>();
|
||||
public List<DecorativeSprite> DecorativeSprites = new List<DecorativeSprite>();
|
||||
public List<ContainedItemSprite> ContainedSprites = new List<ContainedItemSprite>();
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return Vector2.Zero; }
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false)
|
||||
public void Draw(SpriteBatch spriteBatch, bool editing = false, float itemDepth = -1)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Barotrauma
|
||||
{
|
||||
LoadConfig(configPath);
|
||||
}
|
||||
|
||||
public BackgroundCreatureManager(IEnumerable<string> files)
|
||||
{
|
||||
foreach(var file in files)
|
||||
@@ -29,14 +30,26 @@ namespace Barotrauma
|
||||
LoadConfig(file);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadConfig(string configPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configPath);
|
||||
if (doc == null || doc.Root == null) return;
|
||||
if (doc == null) { return; }
|
||||
var mainElement = doc.Root;
|
||||
if (mainElement.IsOverride())
|
||||
{
|
||||
mainElement = doc.Root.FirstElement();
|
||||
prefabs.Clear();
|
||||
DebugConsole.NewMessage($"Overriding all background creatures with '{configPath}'", Color.Yellow);
|
||||
}
|
||||
else if (prefabs.Any())
|
||||
{
|
||||
DebugConsole.NewMessage($"Loading additional background creatures from file '{configPath}'");
|
||||
}
|
||||
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
foreach (XElement element in mainElement.Elements())
|
||||
{
|
||||
prefabs.Add(new BackgroundCreaturePrefab(element));
|
||||
};
|
||||
@@ -46,6 +59,7 @@ namespace Barotrauma
|
||||
DebugConsole.ThrowError(String.Format("Failed to load BackgroundCreatures from {0}", configPath), e);
|
||||
}
|
||||
}
|
||||
|
||||
public void SpawnSprites(int count, Vector2? position = null)
|
||||
{
|
||||
activeSprites.Clear();
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (subElement.Name.ToString().ToLowerInvariant() != "sprite") continue;
|
||||
|
||||
Sprite = new Sprite(subElement);
|
||||
Sprite = new Sprite(subElement, lazyLoad: true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Barotrauma
|
||||
var newDeformation = SpriteDeformation.Load(animationElement, Prefab.Name);
|
||||
if (newDeformation != null)
|
||||
{
|
||||
newDeformation.DeformationParams = Prefab.SpriteDeformations[j].DeformationParams;
|
||||
newDeformation.Params = Prefab.SpriteDeformations[j].Params;
|
||||
spriteDeformations.Add(newDeformation);
|
||||
j++;
|
||||
}
|
||||
|
||||
@@ -72,6 +72,11 @@ namespace Barotrauma.Lights
|
||||
|
||||
private float ambientLightUpdateTimer;
|
||||
|
||||
public IEnumerable<LightSource> Lights
|
||||
{
|
||||
get { return lights; }
|
||||
}
|
||||
|
||||
public LightManager(GraphicsDevice graphics, ContentManager content)
|
||||
{
|
||||
lights = new List<LightSource>();
|
||||
|
||||
@@ -10,15 +10,11 @@ namespace Barotrauma.Lights
|
||||
{
|
||||
class LightSourceParams : ISerializableEntity
|
||||
{
|
||||
public string Name => "LightSource";
|
||||
public string Name => "Light Source";
|
||||
|
||||
public bool Persistent;
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new Dictionary<string, SerializableProperty>();
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties { get; private set; } = new Dictionary<string, SerializableProperty>();
|
||||
|
||||
[Serialize("1.0,1.0,1.0,1.0", true), Editable]
|
||||
public Color Color
|
||||
@@ -28,6 +24,7 @@ namespace Barotrauma.Lights
|
||||
}
|
||||
|
||||
private float range;
|
||||
|
||||
[Serialize(100.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 2048.0f)]
|
||||
public float Range
|
||||
{
|
||||
@@ -64,7 +61,7 @@ namespace Barotrauma.Lights
|
||||
|
||||
public LightSourceParams(XElement element)
|
||||
{
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
Deserialize(element);
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
@@ -103,6 +100,17 @@ namespace Barotrauma.Lights
|
||||
Range = range;
|
||||
Color = color;
|
||||
}
|
||||
|
||||
public bool Deserialize(XElement element)
|
||||
{
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||
return SerializableProperties != null;
|
||||
}
|
||||
|
||||
public void Serialize(XElement element)
|
||||
{
|
||||
SerializableProperty.SerializeProperties(this, element, true);
|
||||
}
|
||||
}
|
||||
|
||||
class LightSource
|
||||
@@ -893,13 +901,21 @@ namespace Barotrauma.Lights
|
||||
|
||||
if (GameMain.DebugDraw)
|
||||
{
|
||||
Vector2 drawPos = position;
|
||||
if (ParentSub != null) { drawPos += ParentSub.DrawPosition; }
|
||||
drawPos.Y = -drawPos.Y;
|
||||
|
||||
if (CastShadows && Screen.Selected == GameMain.SubEditorScreen)
|
||||
{
|
||||
GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 20, Vector2.One * 40, Color.Orange, isFilled: false);
|
||||
GUI.DrawLine(spriteBatch, drawPos - Vector2.One * 20, drawPos + Vector2.One * 20, Color.Orange);
|
||||
GUI.DrawLine(spriteBatch, drawPos - new Vector2(1.0f, -1.0f) * 20, drawPos + new Vector2(1.0f, -1.0f) * 20, Color.Orange);
|
||||
}
|
||||
|
||||
//visualize light recalculations
|
||||
float timeSinceRecalculation = (float)Timing.TotalTime - lastRecalculationTime;
|
||||
if (timeSinceRecalculation < 0.1f)
|
||||
{
|
||||
Vector2 drawPos = position;
|
||||
if (ParentSub != null) drawPos += ParentSub.DrawPosition;
|
||||
drawPos.Y = -drawPos.Y;
|
||||
GUI.DrawRectangle(spriteBatch, drawPos - Vector2.One * 10, Vector2.One * 20, Color.Red * (1.0f - timeSinceRecalculation * 10.0f), isFilled: true);
|
||||
GUI.DrawLine(spriteBatch, drawPos - Vector2.One * Range, drawPos + Vector2.One * Range, Color);
|
||||
GUI.DrawLine(spriteBatch, drawPos - new Vector2(1.0f, -1.0f) * Range, drawPos + new Vector2(1.0f, -1.0f) * Range, Color);
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Barotrauma
|
||||
|
||||
public virtual void Draw(SpriteBatch spriteBatch, bool editing, bool back = true) { }
|
||||
|
||||
public virtual void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect) { }
|
||||
public virtual void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect, bool editing) { }
|
||||
|
||||
/// <summary>
|
||||
/// Update the selection logic in submarine editor
|
||||
|
||||
@@ -170,9 +170,9 @@ namespace Barotrauma
|
||||
Draw(spriteBatch, editing, back, null);
|
||||
}
|
||||
|
||||
public override void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect)
|
||||
public override void DrawDamage(SpriteBatch spriteBatch, Effect damageEffect, bool editing)
|
||||
{
|
||||
Draw(spriteBatch, false, false, damageEffect);
|
||||
Draw(spriteBatch, editing, false, damageEffect);
|
||||
}
|
||||
|
||||
private void Draw(SpriteBatch spriteBatch, bool editing, bool back = true, Effect damageEffect = null)
|
||||
@@ -265,7 +265,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (back == depth > 0.5f || editing)
|
||||
if (back == depth > 0.5f)
|
||||
{
|
||||
SpriteEffects oldEffects = prefab.sprite.effects;
|
||||
prefab.sprite.effects ^= SpriteEffects;
|
||||
|
||||
@@ -235,7 +235,7 @@ namespace Barotrauma
|
||||
foreach (MapEntity e in entitiesToRender)
|
||||
{
|
||||
if (e.DrawDamageEffect)
|
||||
e.DrawDamage(spriteBatch, damageEffect);
|
||||
e.DrawDamage(spriteBatch, damageEffect, editing);
|
||||
}
|
||||
if (damageEffect != null)
|
||||
{
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace Barotrauma
|
||||
}
|
||||
};
|
||||
jobDropDown.AddItem(TextManager.Get("Any"), null);
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.List)
|
||||
foreach (JobPrefab jobPrefab in JobPrefab.List.Values)
|
||||
{
|
||||
jobDropDown.AddItem(jobPrefab.Name, jobPrefab);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Barotrauma.Networking
|
||||
struct TempClient
|
||||
{
|
||||
public string Name;
|
||||
public UInt16 NameID;
|
||||
public UInt64 SteamID;
|
||||
public byte ID;
|
||||
public UInt16 CharacterID;
|
||||
|
||||
@@ -18,6 +18,22 @@ namespace Barotrauma.Networking
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
private string name;
|
||||
|
||||
private UInt16 nameId = 0;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
public void SetName(string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value)) { return; }
|
||||
name = value.Replace(":", "").Replace(";", "");
|
||||
nameId++;
|
||||
}
|
||||
|
||||
private ClientPeer clientPeer;
|
||||
public ClientPeer ClientPeer { get { return clientPeer; } }
|
||||
|
||||
@@ -213,7 +229,7 @@ namespace Barotrauma.Networking
|
||||
Hull.EditFire = false;
|
||||
Hull.EditWater = false;
|
||||
|
||||
Name = newName;
|
||||
SetName(newName);
|
||||
|
||||
entityEventManager = new ClientEntityEventManager(this);
|
||||
|
||||
@@ -221,7 +237,7 @@ namespace Barotrauma.Networking
|
||||
fileReceiver.OnFinished += OnFileReceived;
|
||||
fileReceiver.OnTransferFailed += OnTransferFailed;
|
||||
|
||||
characterInfo = new CharacterInfo(Character.HumanConfigFile, name, null)
|
||||
characterInfo = new CharacterInfo(Character.HumanSpeciesName, name, null)
|
||||
{
|
||||
Job = null
|
||||
};
|
||||
@@ -311,6 +327,7 @@ namespace Barotrauma.Networking
|
||||
translatedEndpoint = endpoint;
|
||||
}
|
||||
clientPeer.OnDisconnect = OnDisconnect;
|
||||
clientPeer.OnDisconnectMessageReceived = HandleDisconnectMessage;
|
||||
clientPeer.OnInitializationComplete = () =>
|
||||
{
|
||||
if (SteamManager.IsInitialized)
|
||||
@@ -323,6 +340,8 @@ namespace Barotrauma.Networking
|
||||
canStart = true;
|
||||
connected = true;
|
||||
|
||||
VoipClient = new VoipClient(this, clientPeer);
|
||||
|
||||
if (Screen.Selected != GameMain.GameScreen)
|
||||
{
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
@@ -591,13 +610,17 @@ namespace Barotrauma.Networking
|
||||
respawnManager.Update(deltaTime);
|
||||
}
|
||||
|
||||
if (updateTimer > DateTime.Now) { return; }
|
||||
SendIngameUpdate();
|
||||
if (updateTimer <= DateTime.Now)
|
||||
{
|
||||
SendIngameUpdate();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (updateTimer > DateTime.Now) { return; }
|
||||
SendLobbyUpdate();
|
||||
if (updateTimer <= DateTime.Now)
|
||||
{
|
||||
SendLobbyUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
if (serverSettings.VoiceChatEnabled)
|
||||
@@ -615,8 +638,11 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
// Update current time
|
||||
updateTimer = DateTime.Now + updateInterval;
|
||||
if (updateTimer <= DateTime.Now)
|
||||
{
|
||||
// Update current time
|
||||
updateTimer = DateTime.Now + updateInterval;
|
||||
}
|
||||
}
|
||||
|
||||
private CoroutineHandle startGameCoroutine;
|
||||
@@ -641,6 +667,9 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
errorMsg += "\nInner exception: " + e.InnerException.Message + "\n" + e.InnerException.StackTrace;
|
||||
}
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Error while reading an ingame update message from server.", e);
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.ReadDataMessage:ReadIngameUpdate", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
throw;
|
||||
}
|
||||
@@ -671,10 +700,21 @@ namespace Barotrauma.Networking
|
||||
IWriteMessage readyToStartMsg = new WriteOnlyMessage();
|
||||
readyToStartMsg.Write((byte)ClientPacketHeader.RESPONSE_STARTGAME);
|
||||
|
||||
MultiPlayerCampaign campaign = GameMain.NetLobbyScreen.SelectedMode == GameMain.GameSession?.GameMode.Preset ?
|
||||
GameMain.GameSession?.GameMode as MultiPlayerCampaign : null;
|
||||
|
||||
GameMain.NetLobbyScreen.UsingShuttle = usingShuttle;
|
||||
bool readyToStart =
|
||||
GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList) &&
|
||||
GameMain.NetLobbyScreen.TrySelectSub(shuttleName, shuttleHash, GameMain.NetLobbyScreen.ShuttleList.ListBox);
|
||||
bool readyToStart;
|
||||
if (campaign == null)
|
||||
{
|
||||
readyToStart = GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList) &&
|
||||
GameMain.NetLobbyScreen.TrySelectSub(shuttleName, shuttleHash, GameMain.NetLobbyScreen.ShuttleList.ListBox);
|
||||
}
|
||||
else
|
||||
{
|
||||
readyToStart = !fileReceiver.ActiveTransfers.Any(c => c.FileType == FileTransferType.CampaignSave) &&
|
||||
(campaign.LastSaveID == campaign.PendingSaveID);
|
||||
}
|
||||
readyToStartMsg.Write(readyToStart);
|
||||
|
||||
WriteCharacterInfo(readyToStartMsg);
|
||||
@@ -741,18 +781,16 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisconnect(string disconnectMsg)
|
||||
{
|
||||
HandleDisconnectMessage(disconnectMsg);
|
||||
}
|
||||
|
||||
private void HandleDisconnectMessage(string disconnectMsg)
|
||||
private void OnDisconnect()
|
||||
{
|
||||
if (SteamManager.IsInitialized)
|
||||
{
|
||||
SteamManager.Instance.User.ClearRichPresence();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleDisconnectMessage(string disconnectMsg)
|
||||
{
|
||||
disconnectMsg = disconnectMsg ?? "";
|
||||
|
||||
string[] splitMsg = disconnectMsg.Split('/');
|
||||
@@ -910,9 +948,13 @@ namespace Barotrauma.Networking
|
||||
private void ReadTraitorMessage(IReadMessage inc)
|
||||
{
|
||||
TraitorMessageType messageType = (TraitorMessageType)inc.ReadByte();
|
||||
string missionIdentifier = inc.ReadString();
|
||||
string message = inc.ReadString();
|
||||
message = TextManager.GetServerMessage(message);
|
||||
|
||||
var missionPrefab = TraitorMissionPrefab.List.Find(t => t.Identifier == missionIdentifier);
|
||||
Sprite icon = missionPrefab?.Icon;
|
||||
|
||||
switch(messageType) {
|
||||
case TraitorMessageType.Objective:
|
||||
var isTraitor = !string.IsNullOrEmpty(message);
|
||||
@@ -932,7 +974,11 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.NewMessage(message);
|
||||
break;
|
||||
case TraitorMessageType.ServerMessageBox:
|
||||
new GUIMessageBox("", message);
|
||||
var msgBox = new GUIMessageBox("", message, new string[0], type: GUIMessageBox.Type.InGame, icon: icon);
|
||||
if (msgBox.Icon != null)
|
||||
{
|
||||
msgBox.IconColor = missionPrefab.IconColor;
|
||||
}
|
||||
break;
|
||||
case TraitorMessageType.Server:
|
||||
default:
|
||||
@@ -1137,6 +1183,12 @@ namespace Barotrauma.Networking
|
||||
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
|
||||
}
|
||||
|
||||
if (GameMain.GameSession.Submarine.IsFileCorrupted)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to start a round. Could not load the submarine \"{GameMain.GameSession.Submarine.Name}\".");
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Submarine.MainSubs.Length; i++)
|
||||
{
|
||||
if (!loadSecondSub && i > 0) { break; }
|
||||
@@ -1221,7 +1273,6 @@ namespace Barotrauma.Networking
|
||||
private void ReadInitialUpdate(IReadMessage inc)
|
||||
{
|
||||
myID = inc.ReadByte();
|
||||
VoipClient = new VoipClient(this, clientPeer);
|
||||
|
||||
UInt16 subListCount = inc.ReadUInt16();
|
||||
serverSubmarines.Clear();
|
||||
@@ -1229,16 +1280,14 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
string subName = inc.ReadString();
|
||||
string subHash = inc.ReadString();
|
||||
bool requiredContentPackagesInstalled = inc.ReadBoolean();
|
||||
|
||||
var matchingSub = Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash);
|
||||
if (matchingSub != null)
|
||||
{
|
||||
serverSubmarines.Add(matchingSub);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverSubmarines.Add(new Submarine(Path.Combine(Submarine.SavePath, subName) + ".sub", subHash, false));
|
||||
}
|
||||
var matchingSub =
|
||||
Submarine.SavedSubmarines.FirstOrDefault(s => s.Name == subName && s.MD5Hash.Hash == subHash) ??
|
||||
new Submarine(Path.Combine(Submarine.SavePath, subName) + ".sub", subHash, false);
|
||||
|
||||
matchingSub.RequiredContentPackagesInstalled = requiredContentPackagesInstalled;
|
||||
serverSubmarines.Add(matchingSub);
|
||||
}
|
||||
|
||||
GameMain.NetLobbyScreen.UpdateSubList(GameMain.NetLobbyScreen.SubList, serverSubmarines);
|
||||
@@ -1265,6 +1314,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
byte id = inc.ReadByte();
|
||||
UInt64 steamId = inc.ReadUInt64();
|
||||
UInt16 nameId = inc.ReadUInt16();
|
||||
string name = inc.ReadString();
|
||||
UInt16 characterID = inc.ReadUInt16();
|
||||
bool muted = inc.ReadBoolean();
|
||||
@@ -1274,6 +1324,7 @@ namespace Barotrauma.Networking
|
||||
tempClients.Add(new TempClient
|
||||
{
|
||||
ID = id,
|
||||
NameID = nameId,
|
||||
SteamID = steamId,
|
||||
Name = name,
|
||||
CharacterID = characterID,
|
||||
@@ -1301,6 +1352,7 @@ namespace Barotrauma.Networking
|
||||
ConnectedClients.Add(existingClient);
|
||||
GameMain.NetLobbyScreen.AddPlayer(existingClient);
|
||||
}
|
||||
existingClient.NameID = tc.NameID;
|
||||
existingClient.Character = null;
|
||||
existingClient.Muted = tc.Muted;
|
||||
existingClient.AllowKicking = tc.AllowKicking;
|
||||
@@ -1315,7 +1367,11 @@ namespace Barotrauma.Networking
|
||||
if (existingClient.ID == myID)
|
||||
{
|
||||
existingClient.SetPermissions(permissions, permittedConsoleCommands);
|
||||
name = tc.Name;
|
||||
if (!NetIdUtils.IdMoreRecent(nameId, tc.NameID))
|
||||
{
|
||||
name = tc.Name;
|
||||
nameId = tc.NameID;
|
||||
}
|
||||
if (GameMain.NetLobbyScreen.CharacterNameBox != null &&
|
||||
!GameMain.NetLobbyScreen.CharacterNameBox.Selected)
|
||||
{
|
||||
@@ -1591,6 +1647,7 @@ namespace Barotrauma.Networking
|
||||
outmsg.Write(GameMain.NetLobbyScreen.LastUpdateID);
|
||||
outmsg.Write(ChatMessage.LastID);
|
||||
outmsg.Write(LastClientListUpdateID);
|
||||
outmsg.Write(nameId);
|
||||
outmsg.Write(name);
|
||||
|
||||
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||
@@ -1795,6 +1852,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
SaveUtil.LoadGame(GameMain.GameSession.SavePath, GameMain.GameSession);
|
||||
GameMain.GameSession?.Submarine?.CheckSubsLeftBehind();
|
||||
campaign.LastSaveID = campaign.PendingSaveID;
|
||||
|
||||
DebugConsole.Log("Campaign save received, save ID " + campaign.LastSaveID);
|
||||
@@ -2123,7 +2181,15 @@ namespace Barotrauma.Networking
|
||||
|
||||
public bool SpectateClicked(GUIButton button, object userData)
|
||||
{
|
||||
if (button != null) button.Enabled = false;
|
||||
MultiPlayerCampaign campaign =
|
||||
GameMain.NetLobbyScreen.SelectedMode == GameMain.GameSession?.GameMode.Preset ?
|
||||
GameMain.GameSession?.GameMode as MultiPlayerCampaign : null;
|
||||
if (campaign != null && campaign.LastSaveID < campaign.PendingSaveID)
|
||||
{
|
||||
new GUIMessageBox("", TextManager.Get("campaignfiletransferinprogress"));
|
||||
return false;
|
||||
}
|
||||
if (button != null) { button.Enabled = false; }
|
||||
|
||||
IWriteMessage readyToStartMsg = new WriteOnlyMessage();
|
||||
readyToStartMsg.Write((byte)ClientPacketHeader.RESPONSE_STARTGAME);
|
||||
|
||||
@@ -7,12 +7,14 @@ namespace Barotrauma.Networking
|
||||
abstract class ClientPeer
|
||||
{
|
||||
public delegate void MessageCallback(IReadMessage message);
|
||||
public delegate void DisconnectCallback(string msg);
|
||||
public delegate void DisconnectCallback();
|
||||
public delegate void DisconnectMessageCallback(string message);
|
||||
public delegate void PasswordCallback(int salt, int retries);
|
||||
public delegate void InitializationCompleteCallback();
|
||||
|
||||
public MessageCallback OnMessageReceived;
|
||||
public DisconnectCallback OnDisconnect;
|
||||
public DisconnectMessageCallback OnDisconnectMessageReceived;
|
||||
public PasswordCallback OnRequestPassword;
|
||||
public InitializationCompleteCallback OnInitializationComplete;
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ namespace Barotrauma.Networking
|
||||
case NetConnectionStatus.Disconnected:
|
||||
string disconnectMsg = inc.ReadString();
|
||||
Close(disconnectMsg);
|
||||
OnDisconnectMessageReceived?.Invoke(disconnectMsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -227,7 +228,7 @@ namespace Barotrauma.Networking
|
||||
netClient.Shutdown(msg ?? TextManager.Get("Disconnecting"));
|
||||
netClient = null;
|
||||
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
||||
OnDisconnect?.Invoke(msg);
|
||||
OnDisconnect?.Invoke();
|
||||
}
|
||||
|
||||
public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod)
|
||||
@@ -248,6 +249,13 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
netPeerConfiguration.SimulatedDuplicatesChance = GameMain.Client.SimulatedDuplicatesChance;
|
||||
netPeerConfiguration.SimulatedMinimumLatency = GameMain.Client.SimulatedMinimumLatency;
|
||||
netPeerConfiguration.SimulatedRandomLatency = GameMain.Client.SimulatedRandomLatency;
|
||||
netPeerConfiguration.SimulatedLoss = GameMain.Client.SimulatedLoss;
|
||||
#endif
|
||||
|
||||
NetOutgoingMessage lidgrenMsg = netClient.CreateMessage();
|
||||
byte[] msgData = new byte[msg.LengthBytes];
|
||||
msg.PrepareForSending(ref msgData, out bool isCompressed, out int length);
|
||||
|
||||
@@ -116,6 +116,7 @@ namespace Barotrauma.Networking
|
||||
IReadMessage inc = new ReadOnlyMessage(data, false, 1, dataLength - 1, ServerConnection);
|
||||
string msg = inc.ReadString();
|
||||
Close(msg);
|
||||
OnDisconnectMessageReceived?.Invoke(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -270,8 +271,27 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
heartbeatTimer = 5.0;
|
||||
bool successSend = SteamManager.Instance.Networking.SendP2PPacket(hostSteamId, buf, length + 4, sendType);
|
||||
|
||||
#if DEBUG
|
||||
CoroutineManager.InvokeAfter(() =>
|
||||
{
|
||||
if (Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedLoss && sendType != Facepunch.Steamworks.Networking.SendType.Reliable) { return; }
|
||||
int count = Rand.Range(0.0f, 1.0f) < GameMain.Client.SimulatedDuplicatesChance ? 2 : 1;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Send(buf, length + 4, sendType);
|
||||
}
|
||||
},
|
||||
GameMain.Client.SimulatedMinimumLatency + Rand.Range(0.0f, GameMain.Client.SimulatedRandomLatency));
|
||||
|
||||
#else
|
||||
Send(buf, length + 4, sendType);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void Send(byte[] buf, int length, Facepunch.Steamworks.Networking.SendType sendType)
|
||||
{
|
||||
bool successSend = SteamManager.Instance.Networking.SendP2PPacket(hostSteamId, buf, length + 4, sendType);
|
||||
if (!successSend)
|
||||
{
|
||||
if (sendType != Facepunch.Steamworks.Networking.SendType.Reliable)
|
||||
@@ -332,7 +352,7 @@ namespace Barotrauma.Networking
|
||||
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
||||
hostSteamId = 0;
|
||||
|
||||
OnDisconnect?.Invoke(msg);
|
||||
OnDisconnect?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,6 +414,7 @@ namespace Barotrauma.Networking
|
||||
case NetConnectionStatus.Disconnected:
|
||||
string disconnectMsg = inc.ReadString();
|
||||
Close(disconnectMsg);
|
||||
OnDisconnectMessageReceived?.Invoke(disconnectMsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -429,7 +430,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
isActive = false;
|
||||
|
||||
for (int i=remotePeers.Count-1;i>=0;i--)
|
||||
for (int i = remotePeers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
DisconnectPeer(remotePeers[i], msg ?? DisconnectReason.ServerShutdown.ToString());
|
||||
}
|
||||
@@ -444,7 +445,7 @@ namespace Barotrauma.Networking
|
||||
netClient.Shutdown(msg ?? TextManager.Get("Disconnecting"));
|
||||
netClient = null;
|
||||
|
||||
OnDisconnect?.Invoke(msg);
|
||||
OnDisconnect?.Invoke();
|
||||
|
||||
Steam.SteamManager.Instance.Networking.OnIncomingConnection = null;
|
||||
Steam.SteamManager.Instance.Networking.OnP2PData = null;
|
||||
@@ -478,6 +479,12 @@ namespace Barotrauma.Networking
|
||||
lidgrenMsg.Write((UInt16)length);
|
||||
lidgrenMsg.Write(msgData, 0, length);
|
||||
|
||||
#if DEBUG
|
||||
netPeerConfiguration.SimulatedDuplicatesChance = GameMain.Client.SimulatedDuplicatesChance;
|
||||
netPeerConfiguration.SimulatedMinimumLatency = GameMain.Client.SimulatedMinimumLatency;
|
||||
netPeerConfiguration.SimulatedRandomLatency = GameMain.Client.SimulatedRandomLatency;
|
||||
netPeerConfiguration.SimulatedLoss = GameMain.Client.SimulatedLoss;
|
||||
#endif
|
||||
NetSendResult result = netClient.SendMessage(lidgrenMsg, lidgrenDeliveryMethod);
|
||||
if (result != NetSendResult.Queued && result != NetSendResult.Sent)
|
||||
{
|
||||
|
||||
@@ -758,8 +758,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
karmaSettingsBlocker = new GUIFrame(new RectTransform(Vector2.One, karmaSettingsContainer.RectTransform, Anchor.CenterLeft) { MaxSize = new Point(karmaSettingsList.Content.Rect.Width, int.MaxValue) },
|
||||
style: "InnerFrame");
|
||||
karmaPresetDD.SelectItem(KarmaPreset);
|
||||
karmaSettingsBlocker.Visible = !karmaBox.Selected || KarmaPreset != "custom";
|
||||
GameMain.NetworkMember.KarmaManager.CreateSettingsFrame(karmaSettingsList.Content);
|
||||
karmaPresetDD.OnSelected = (selected, obj) =>
|
||||
{
|
||||
string newKarmaPreset = obj as string;
|
||||
if (newKarmaPreset == KarmaPreset) { return true; }
|
||||
|
||||
List<NetPropertyData> properties = netProperties.Values.ToList();
|
||||
List<object> prevValues = new List<object>();
|
||||
foreach (NetPropertyData prop in netProperties.Values)
|
||||
@@ -772,7 +778,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
|
||||
GameMain.NetworkMember?.KarmaManager?.Save();
|
||||
}
|
||||
KarmaPreset = obj as string;
|
||||
KarmaPreset = newKarmaPreset;
|
||||
GameMain.NetworkMember.KarmaManager.SelectPreset(KarmaPreset);
|
||||
karmaSettingsList.Content.ClearChildren();
|
||||
karmaSettingsBlocker.Visible = !karmaBox.Selected || KarmaPreset != "custom";
|
||||
@@ -783,7 +789,6 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
return true;
|
||||
};
|
||||
karmaPresetDD.SelectItem(KarmaPreset);
|
||||
AssignGUIComponent("KarmaPreset", karmaPresetDD);
|
||||
karmaBox.OnSelected = (tb) =>
|
||||
{
|
||||
@@ -836,16 +841,16 @@ namespace Barotrauma.Networking
|
||||
public bool ToggleSettingsFrame(GUIButton button, object obj)
|
||||
{
|
||||
if (settingsFrame == null)
|
||||
{
|
||||
CreateSettingsFrame();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (KarmaPreset == "custom")
|
||||
{
|
||||
GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
|
||||
GameMain.NetworkMember?.KarmaManager?.Save();
|
||||
}
|
||||
CreateSettingsFrame();
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientAdminWrite(NetFlags.Properties);
|
||||
foreach (NetPropertyData prop in netProperties.Values)
|
||||
{
|
||||
|
||||
@@ -736,14 +736,14 @@ namespace Barotrauma.Steam
|
||||
/// <summary>
|
||||
/// Creates a copy of the specified workshop item in the staging folder and an editor that can be used to edit and update the item
|
||||
/// </summary>
|
||||
public static void CreateWorkshopItemStaging(Workshop.Item existingItem, out Workshop.Editor itemEditor, out ContentPackage contentPackage)
|
||||
public static bool CreateWorkshopItemStaging(Workshop.Item existingItem, out Workshop.Editor itemEditor, out ContentPackage contentPackage)
|
||||
{
|
||||
if (!existingItem.Installed)
|
||||
{
|
||||
itemEditor = null;
|
||||
contentPackage = null;
|
||||
DebugConsole.ThrowError("Cannot edit the workshop item \"" + existingItem.Title + "\" because it has not been installed.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
itemEditor = instance.client.Workshop.EditItem(existingItem.Id);
|
||||
@@ -763,7 +763,7 @@ namespace Barotrauma.Steam
|
||||
TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { existingItem.Title, errorMsg }));
|
||||
itemEditor = null;
|
||||
contentPackage = null;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,7 +773,7 @@ namespace Barotrauma.Steam
|
||||
|
||||
if (contentPackage == null && tempContentPackage.GameVersion <= new Version(0, 9, 1, 0))
|
||||
{
|
||||
//try finding the content package in the lega
|
||||
//try finding the content package from the non-legacy path
|
||||
installedContentPackagePath = Path.GetFullPath(GetWorkshopItemContentPackagePath(tempContentPackage, legacy: false));
|
||||
contentPackage = ContentPackage.List.Find(cp => Path.GetFullPath(cp.Path) == installedContentPackagePath);
|
||||
}
|
||||
@@ -792,8 +792,11 @@ namespace Barotrauma.Steam
|
||||
contentPackage.Path = newPath;
|
||||
itemEditor.Folder = newDir;
|
||||
if (!Directory.Exists(newDir)) { Directory.CreateDirectory(newDir); }
|
||||
if (File.Exists(newPath)) { File.Delete(newPath); }
|
||||
File.Move(installedContentPackagePath, newPath);
|
||||
if (Path.GetFullPath(newPath) != installedContentPackagePath)
|
||||
{
|
||||
if (File.Exists(newPath)) { File.Delete(newPath); }
|
||||
File.Move(installedContentPackagePath, newPath);
|
||||
}
|
||||
//move all files inside the Mods folder
|
||||
foreach (ContentFile cf in contentPackage.Files)
|
||||
{
|
||||
@@ -815,7 +818,7 @@ namespace Barotrauma.Steam
|
||||
string errorMsg = TextManager.GetWithVariable("WorkshopErrorOnEnable", "[itemname]", TextManager.EnsureUTF8(existingItem.Title));
|
||||
new GUIMessageBox(TextManager.Get("Error"), errorMsg);
|
||||
DebugConsole.ThrowError(errorMsg, e);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,6 +849,7 @@ namespace Barotrauma.Steam
|
||||
GameAnalyticsManager.AddErrorEventOnce("SteamManager.CreateWorkshopItemStaging:WriteAllBytesFailed" + previewImagePath,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg + "\n" + e.Message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void StartPublishItem(ContentPackage contentPackage, Workshop.Editor item)
|
||||
@@ -865,11 +869,9 @@ namespace Barotrauma.Steam
|
||||
|
||||
contentPackage.GameVersion = GameMain.Version;
|
||||
contentPackage.Save(contentPackage.Path);
|
||||
|
||||
if (File.Exists(PreviewImageName)) { File.Delete(PreviewImageName); }
|
||||
//move the preview image out of the staging folder, it does not need to be included in the folder sent to Workshop
|
||||
File.Move(Path.GetFullPath(Path.Combine(item.Folder, PreviewImageName)), PreviewImageName);
|
||||
item.PreviewImage = Path.GetFullPath(PreviewImageName);
|
||||
|
||||
string previewImagePath = Path.GetFullPath(Path.Combine(item.Folder, PreviewImageName));
|
||||
item.PreviewImage = File.Exists(previewImagePath) ? previewImagePath : null;
|
||||
|
||||
CoroutineManager.StartCoroutine(PublishItem(item));
|
||||
}
|
||||
@@ -904,7 +906,7 @@ namespace Barotrauma.Steam
|
||||
/// <summary>
|
||||
/// Enables a workshop item by moving it to the game folder.
|
||||
/// </summary>
|
||||
public static bool EnableWorkShopItem(Workshop.Item item, bool allowFileOverwrite, out string errorMsg)
|
||||
public static bool EnableWorkShopItem(Workshop.Item item, bool allowFileOverwrite, out string errorMsg, bool selectContentPackage = true)
|
||||
{
|
||||
if (!item.Installed)
|
||||
{
|
||||
@@ -959,19 +961,24 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
newPackage.Save(newContentPackagePath);
|
||||
ContentPackage.List.Add(newPackage);
|
||||
if (newPackage.CorePackage)
|
||||
|
||||
if (selectContentPackage)
|
||||
{
|
||||
//if enabling a core package, disable all other core packages
|
||||
GameMain.Config.SelectedContentPackages.RemoveWhere(cp => cp.CorePackage);
|
||||
if (newPackage.CorePackage)
|
||||
{
|
||||
//if enabling a core package, disable all other core packages
|
||||
GameMain.Config.SelectedContentPackages.RemoveAll(cp => cp.CorePackage);
|
||||
}
|
||||
GameMain.Config.SelectContentPackage(newPackage);
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
foreach (ContentFile cf in newPackage.Files)
|
||||
{
|
||||
if (cf.Type == ContentType.Submarine)
|
||||
{
|
||||
Submarine.RefreshSavedSub(cf.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
GameMain.Config.SelectedContentPackages.Add(newPackage);
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
|
||||
if (newPackage.Files.Any(f => f.Type == ContentType.Submarine))
|
||||
{
|
||||
Submarine.RefreshSavedSubs();
|
||||
}
|
||||
|
||||
errorMsg = "";
|
||||
return true;
|
||||
}
|
||||
@@ -1166,7 +1173,8 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
|
||||
ContentPackage.List.RemoveAll(cp => System.IO.Path.GetFullPath(cp.Path) == System.IO.Path.GetFullPath(installedContentPackagePath));
|
||||
GameMain.Config.SelectedContentPackages.RemoveWhere(cp => !ContentPackage.List.Contains(cp));
|
||||
GameMain.Config.SelectedContentPackages.RemoveAll(cp => !ContentPackage.List.Contains(cp));
|
||||
ContentPackage.SortContentPackages();
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -1218,7 +1226,7 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
metaDataPath = Path.Combine(item.Directory.FullName, MetadataFileName);
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
catch (ArgumentException)
|
||||
{
|
||||
string errorMessage = "Metadata file for the Workshop item \"" + item.Title +
|
||||
"\" not found. Could not combine path (" + (item.Directory.FullName ?? "directory name empty") + ").";
|
||||
@@ -1255,7 +1263,7 @@ namespace Barotrauma.Steam
|
||||
|
||||
public static bool CheckWorkshopItemUpToDate(Workshop.Item item)
|
||||
{
|
||||
if (!item.Installed) return false;
|
||||
if (!item.Installed) { return false; }
|
||||
|
||||
string metaDataPath = Path.Combine(item.Directory.FullName, MetadataFileName);
|
||||
if (!File.Exists(metaDataPath))
|
||||
@@ -1274,6 +1282,22 @@ namespace Barotrauma.Steam
|
||||
return item.Modified <= myPackage.InstallTime.Value;
|
||||
}
|
||||
|
||||
|
||||
public static bool CheckWorkshopItemSelected(Workshop.Item item)
|
||||
{
|
||||
if (!item.Installed) { return false; }
|
||||
|
||||
string metaDataPath = Path.Combine(item.Directory.FullName, MetadataFileName);
|
||||
if (!File.Exists(metaDataPath))
|
||||
{
|
||||
DebugConsole.ThrowError("Metadata file for the Workshop item \"" + item.Title + "\" not found. The file may be corrupted.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ContentPackage steamPackage = new ContentPackage(metaDataPath);
|
||||
return GameMain.Config.SelectedContentPackages.Any(cp => cp.Name == steamPackage.Name);
|
||||
}
|
||||
|
||||
public static bool AutoUpdateWorkshopItems()
|
||||
{
|
||||
if (instance == null || !instance.isInitialized) { return false; }
|
||||
@@ -1290,8 +1314,9 @@ namespace Barotrauma.Steam
|
||||
itemsUpdated = false;
|
||||
foreach (var item in q.Items)
|
||||
{
|
||||
if (item.Installed && CheckWorkshopItemEnabled(item) && !CheckWorkshopItemUpToDate(item))
|
||||
try
|
||||
{
|
||||
if (!item.Installed || !CheckWorkshopItemEnabled(item) || CheckWorkshopItemUpToDate(item)) { continue; }
|
||||
if (!UpdateWorkshopItem(item, out string errorMsg))
|
||||
{
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
@@ -1305,6 +1330,16 @@ namespace Barotrauma.Steam
|
||||
itemsUpdated = true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
new GUIMessageBox(
|
||||
TextManager.Get("Error"),
|
||||
TextManager.GetWithVariables("WorkshopItemUpdateFailed", new string[2] { "[itemname]", "[errormessage]" }, new string[2] { item.Title, e.Message + ", " + e.TargetSite }));
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"SteamManager.AutoUpdateWorkshopItems:" + e.Message,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to autoupdate workshop item \"" + item.Title + "\". " + e.Message + "\n" + e.StackTrace);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1328,8 +1363,9 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
errorMsg = "";
|
||||
if (!item.Installed) { return false; }
|
||||
bool wasSelected = CheckWorkshopItemSelected(item);
|
||||
if (!DisableWorkShopItem(item, out errorMsg)) { return false; }
|
||||
if (!EnableWorkShopItem(item, allowFileOverwrite: false, errorMsg: out errorMsg)) { return false; }
|
||||
if (!EnableWorkShopItem(item, allowFileOverwrite: false, errorMsg: out errorMsg, selectContentPackage: wasSelected)) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Particles
|
||||
{
|
||||
@@ -10,21 +11,47 @@ namespace Barotrauma.Particles
|
||||
|
||||
public DecalManager()
|
||||
{
|
||||
prefabs = new Dictionary<string, DecalPrefab>();
|
||||
var decalElements = new Dictionary<string, XElement>();
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.Decals))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
if (doc == null) { continue; }
|
||||
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
bool allowOverriding = false;
|
||||
var mainElement = doc.Root;
|
||||
if (doc.Root.IsOverride())
|
||||
{
|
||||
if (prefabs.ContainsKey(element.Name.ToString()))
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + configFile + "! Each decal prefab must have a unique name.");
|
||||
continue;
|
||||
}
|
||||
prefabs.Add(element.Name.ToString(), new DecalPrefab(element));
|
||||
mainElement = doc.Root.FirstElement();
|
||||
allowOverriding = true;
|
||||
}
|
||||
|
||||
foreach (XElement sourceElement in mainElement.Elements())
|
||||
{
|
||||
var element = sourceElement.IsOverride() ? sourceElement.FirstElement() : sourceElement;
|
||||
string name = element.Name.ToString().ToLowerInvariant();
|
||||
if (decalElements.ContainsKey(name))
|
||||
{
|
||||
if (allowOverriding || sourceElement.IsOverride())
|
||||
{
|
||||
DebugConsole.NewMessage($"Overriding the existing decal prefab '{name}' using the file '{configFile}'", Color.Yellow);
|
||||
decalElements.Remove(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in '{configFile}': Duplicate decal prefab '{name}' found in '{configFile}'! Each decal prefab must have a unique name. " +
|
||||
"Use <override></override> tags to override prefabs.");
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
decalElements.Add(name, element);
|
||||
}
|
||||
}
|
||||
//prefabs = decalElements.ToDictionary(d => d.Key, d => new DecalPrefab(d.Value));
|
||||
prefabs = new Dictionary<string, DecalPrefab>();
|
||||
foreach (var kvp in decalElements)
|
||||
{
|
||||
prefabs.Add(kvp.Key, new DecalPrefab(kvp.Value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,22 +63,48 @@ namespace Barotrauma.Particles
|
||||
|
||||
public void LoadPrefabs()
|
||||
{
|
||||
prefabs = new Dictionary<string, ParticlePrefab>();
|
||||
var particleElements = new Dictionary<string, XElement>();
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.Particles))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
if (doc == null) { continue; }
|
||||
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
bool allowOverriding = false;
|
||||
var mainElement = doc.Root;
|
||||
if (doc.Root.IsOverride())
|
||||
{
|
||||
if (prefabs.ContainsKey(element.Name.ToString()))
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + configFile + "! Each particle prefab must have a unique name.");
|
||||
continue;
|
||||
}
|
||||
prefabs.Add(element.Name.ToString(), new ParticlePrefab(element));
|
||||
mainElement = doc.Root.FirstElement();
|
||||
allowOverriding = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XElement sourceElement in mainElement.Elements())
|
||||
{
|
||||
var element = sourceElement.IsOverride() ? sourceElement.FirstElement() : sourceElement;
|
||||
string name = element.Name.ToString().ToLowerInvariant();
|
||||
if (particleElements.ContainsKey(name))
|
||||
{
|
||||
if (allowOverriding || sourceElement.IsOverride())
|
||||
{
|
||||
DebugConsole.NewMessage($"Overriding the existing particle prefab '{name}' using the file '{configFile}'", Color.Yellow);
|
||||
particleElements.Remove(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError($"Error in '{configFile}': Duplicate particle prefab '{name}' found in '{configFile}'! Each particle prefab must have a unique name. " +
|
||||
"Use <override></override> tags to override prefabs.");
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
particleElements.Add(name, element);
|
||||
}
|
||||
}
|
||||
//prefabs = particleElements.ToDictionary(p => p.Key, p => new ParticlePrefab(p.Value));
|
||||
prefabs = new Dictionary<string, ParticlePrefab>();
|
||||
foreach (var kvp in particleElements)
|
||||
{
|
||||
prefabs.Add(kvp.Key, new ParticlePrefab(kvp.Value));
|
||||
}
|
||||
}
|
||||
|
||||
public Particle CreateParticle(string prefabName, Vector2 position, float angle, float speed, Hull hullGuess = null)
|
||||
|
||||
@@ -17,12 +17,12 @@ namespace Barotrauma.Particles
|
||||
private set;
|
||||
}
|
||||
|
||||
[Editable(0.0f, float.MaxValue, ToolTip = "How many seconds the particle remains alive."), Serialize(5.0f, false)]
|
||||
[Editable(0.0f, float.MaxValue), Serialize(5.0f, false, description: "How many seconds the particle remains alive.")]
|
||||
public float LifeTime { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "How long it takes for the particle to appear after spawning it."), Serialize(0.0f, false)]
|
||||
[Editable, Serialize(0.0f, false, description: "How long it takes for the particle to appear after spawning it.")]
|
||||
public float StartDelayMin { get; private set; }
|
||||
[Editable(ToolTip = "How long it takes for the particle to appear after spawning it."), Serialize(0.0f, false)]
|
||||
[Editable, Serialize(0.0f, false, description: "How long it takes for the particle to appear after spawning it.")]
|
||||
public float StartDelayMax { get; private set; }
|
||||
//movement -----------------------------------------
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Barotrauma.Particles
|
||||
private float startRotationMin;
|
||||
public float StartRotationMinRad { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "The minimum initial rotation of the particle (in degrees)."), Serialize(0.0f, false)]
|
||||
[Editable, Serialize(0.0f, false, description: "The minimum initial rotation of the particle (in degrees).")]
|
||||
public float StartRotationMin
|
||||
{
|
||||
get { return startRotationMin; }
|
||||
@@ -71,7 +71,7 @@ namespace Barotrauma.Particles
|
||||
private float startRotationMax;
|
||||
public float StartRotationMaxRad { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "The maximum initial rotation of the particle (in degrees)."), Serialize(0.0f, false)]
|
||||
[Editable, Serialize(0.0f, false, description: "The maximum initial rotation of the particle (in degrees).")]
|
||||
public float StartRotationMax
|
||||
{
|
||||
get { return startRotationMax; }
|
||||
@@ -82,19 +82,19 @@ namespace Barotrauma.Particles
|
||||
}
|
||||
}
|
||||
|
||||
[Editable(ToolTip = "Should the particle face the direction it's moving towards."), Serialize(false, false)]
|
||||
[Editable, Serialize(false, false, description: "Should the particle face the direction it's moving towards.")]
|
||||
public bool RotateToDirection { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "Drag applied to the particle when it's moving through air."), Serialize(0.0f, false)]
|
||||
[Editable, Serialize(0.0f, false, description: "Drag applied to the particle when it's moving through air.")]
|
||||
public float Drag { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "Drag applied to the particle when it's moving through water."), Serialize(0.0f, false)]
|
||||
[Editable, Serialize(0.0f, false, description: "Drag applied to the particle when it's moving through water.")]
|
||||
public float WaterDrag { get; private set; }
|
||||
|
||||
private Vector2 velocityChange;
|
||||
public Vector2 VelocityChangeDisplay { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "How much the velocity of the particle changes per second."), Serialize("0.0,0.0", false)]
|
||||
[Editable, Serialize("0.0,0.0", false, description: "How much the velocity of the particle changes per second.")]
|
||||
public Vector2 VelocityChange
|
||||
{
|
||||
get { return velocityChange; }
|
||||
@@ -108,7 +108,7 @@ namespace Barotrauma.Particles
|
||||
private Vector2 velocityChangeWater;
|
||||
public Vector2 VelocityChangeWaterDisplay { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "How much the velocity of the particle changes per second when in water."), Serialize("0.0,0.0", false)]
|
||||
[Editable, Serialize("0.0,0.0", false, description: "How much the velocity of the particle changes per second when in water.")]
|
||||
public Vector2 VelocityChangeWater
|
||||
{
|
||||
get { return velocityChangeWater; }
|
||||
@@ -119,62 +119,62 @@ namespace Barotrauma.Particles
|
||||
}
|
||||
}
|
||||
|
||||
[Editable(0.0f, 10000.0f, ToolTip = "Drag applied to the particle when it's moving through water."), Serialize(0.0f, false)]
|
||||
[Editable(0.0f, 10000.0f), Serialize(0.0f, false, description: "Drag applied to the particle when it's moving through water.")]
|
||||
public float CollisionRadius { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "Does the particle collide with the walls of the submarine and the level."), Serialize(false, false)]
|
||||
[Editable, Serialize(false, false, description: "Does the particle collide with the walls of the submarine and the level.")]
|
||||
public bool UseCollision { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "Does the particle disappear when it collides with something."), Serialize(false, false)]
|
||||
[Editable, Serialize(false, false, description: "Does the particle disappear when it collides with something.")]
|
||||
public bool DeleteOnCollision { get; private set; }
|
||||
|
||||
[Editable(0.0f, 1.0f, ToolTip = "The friction coefficient of the particle, i.e. how much it slows down when it's sliding against a surface."), Serialize(0.5f, false)]
|
||||
[Editable(0.0f, 1.0f), Serialize(0.5f, false, description: "The friction coefficient of the particle, i.e. how much it slows down when it's sliding against a surface.")]
|
||||
public float Friction { get; private set; }
|
||||
|
||||
[Editable(0.0f, 1.0f, ToolTip = "How much of the particle's velocity is conserved when it collides with something, i.e. the \"bounciness\" of the particle. (1.0 = the particle stops completely).")]
|
||||
[Serialize(0.5f, false)]
|
||||
[Editable(0.0f, 1.0f)]
|
||||
[Serialize(0.5f, false, description: "How much of the particle's velocity is conserved when it collides with something, i.e. the \"bounciness\" of the particle. (1.0 = the particle stops completely).")]
|
||||
public float Restitution { get; private set; }
|
||||
|
||||
//size -----------------------------------------
|
||||
|
||||
[Editable(ToolTip = "The minimum initial size of the particle."), Serialize("1.0,1.0", false)]
|
||||
[Editable, Serialize("1.0,1.0", false, description: "The minimum initial size of the particle.")]
|
||||
public Vector2 StartSizeMin { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "The maximum initial size of the particle."), Serialize("1.0,1.0", false)]
|
||||
[Editable, Serialize("1.0,1.0", false, description: "The maximum initial size of the particle.")]
|
||||
public Vector2 StartSizeMax { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
||||
[Serialize("0.0,0.0", false)]
|
||||
[Editable]
|
||||
[Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
||||
public Vector2 SizeChangeMin { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
||||
[Serialize("0.0,0.0", false)]
|
||||
[Editable]
|
||||
[Serialize("0.0,0.0", false, description: "How much the size of the particle changes per second. The rate of growth for each particle is randomize between SizeChangeMin and SizeChangeMax.")]
|
||||
public Vector2 SizeChangeMax { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "How many seconds it takes for the particle to grow to it's initial size.")]
|
||||
[Serialize(0.0f, false)]
|
||||
[Editable]
|
||||
[Serialize(0.0f, false, description: "How many seconds it takes for the particle to grow to it's initial size.")]
|
||||
public float GrowTime { get; private set; }
|
||||
|
||||
//rendering -----------------------------------------
|
||||
|
||||
[Editable(ToolTip = "The initial color of the particle."), Serialize("1.0,1.0,1.0,1.0", false)]
|
||||
[Editable, Serialize("1.0,1.0,1.0,1.0", false, description: "The initial color of the particle.")]
|
||||
public Color StartColor { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "The color of the particle at the end of its lifetime."), Serialize("1.0,1.0,1.0,1.0", false)]
|
||||
[Editable, Serialize("1.0,1.0,1.0,1.0", false, description: "The color of the particle at the end of its lifetime.")]
|
||||
public Color EndColor { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "Should the particle be rendered in air, water or both."), Serialize(DrawTargetType.Air, false)]
|
||||
[Editable, Serialize(DrawTargetType.Air, false, description: "Should the particle be rendered in air, water or both.")]
|
||||
public DrawTargetType DrawTarget { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "The type of blending to use when rendering the particle."), Serialize(ParticleBlendState.AlphaBlend, false)]
|
||||
[Editable, Serialize(ParticleBlendState.AlphaBlend, false, description: "The type of blending to use when rendering the particle.")]
|
||||
public ParticleBlendState BlendState { get; private set; }
|
||||
|
||||
//animation -----------------------------------------
|
||||
|
||||
[Editable(0.0f, float.MaxValue, ToolTip = "The duration of the particle's animation cycle (if it's animated)."), Serialize(1.0f, false)]
|
||||
[Editable(0.0f, float.MaxValue), Serialize(1.0f, false, description: "The duration of the particle's animation cycle (if it's animated).")]
|
||||
public float AnimDuration { get; private set; }
|
||||
|
||||
[Editable(ToolTip = "Should the sprite animation be looped, or stay at the last frame when the animation finishes."), Serialize(true, false)]
|
||||
[Editable, Serialize(true, false, description: "Should the sprite animation be looped, or stay at the last frame when the animation finishes.")]
|
||||
public bool LoopAnim { get; private set; }
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Barotrauma
|
||||
get { return bodyShapeTexture; }
|
||||
}
|
||||
|
||||
public void Draw(DeformableSprite deformSprite, Camera cam, Vector2 scale, Color color)
|
||||
public void Draw(DeformableSprite deformSprite, Camera cam, Vector2 scale, Color color, bool mirror = false)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
UpdateDrawPosition();
|
||||
@@ -25,17 +25,23 @@ namespace Barotrauma
|
||||
new Vector3(DrawPosition, MathHelper.Clamp(deformSprite.Sprite.Depth, 0, 1)),
|
||||
deformSprite.Origin,
|
||||
-DrawRotation,
|
||||
scale,
|
||||
color,
|
||||
flip: Dir < 0);
|
||||
scale, color, Dir < 0, mirror);
|
||||
}
|
||||
|
||||
public void Draw(SpriteBatch spriteBatch, Sprite sprite, Color color, float? depth = null, float scale = 1.0f)
|
||||
public void Draw(SpriteBatch spriteBatch, Sprite sprite, Color color, float? depth = null, float scale = 1.0f, bool mirrorX = false, bool mirrorY = false)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
UpdateDrawPosition();
|
||||
if (sprite == null) return;
|
||||
SpriteEffects spriteEffect = (Dir == 1.0f) ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
|
||||
if (mirrorX)
|
||||
{
|
||||
spriteEffect = spriteEffect == SpriteEffects.None ? SpriteEffects.FlipHorizontally : SpriteEffects.None;
|
||||
}
|
||||
if (mirrorY)
|
||||
{
|
||||
spriteEffect |= SpriteEffects.FlipVertically;
|
||||
}
|
||||
sprite.Draw(spriteBatch, new Vector2(DrawPosition.X, -DrawPosition.Y), color, -drawRotation, scale, spriteEffect, depth);
|
||||
}
|
||||
|
||||
@@ -134,14 +140,17 @@ namespace Barotrauma
|
||||
rot -= MathHelper.PiOver2;
|
||||
}
|
||||
|
||||
spriteBatch.Draw(
|
||||
bodyShapeTexture,
|
||||
new Vector2(DrawPosition.X, -DrawPosition.Y),
|
||||
null,
|
||||
color,
|
||||
rot,
|
||||
new Vector2(bodyShapeTexture.Width / 2, bodyShapeTexture.Height / 2),
|
||||
1.0f / bodyShapeTextureScale, SpriteEffects.None, 0.0f);
|
||||
if (bodyShapeTexture != null)
|
||||
{
|
||||
spriteBatch.Draw(
|
||||
bodyShapeTexture,
|
||||
new Vector2(DrawPosition.X, -DrawPosition.Y),
|
||||
null,
|
||||
color,
|
||||
rot,
|
||||
new Vector2(bodyShapeTexture.Width / 2, bodyShapeTexture.Height / 2),
|
||||
1.0f / bodyShapeTextureScale, SpriteEffects.None, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public PosInfo ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime, string parentDebugName)
|
||||
|
||||
@@ -9,8 +9,7 @@ using Barotrauma.Steam;
|
||||
using System.Diagnostics;
|
||||
|
||||
#if WINDOWS
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using SharpDX;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
@@ -31,135 +30,41 @@ namespace Barotrauma
|
||||
[STAThread]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
SteamManager.Initialize();
|
||||
GameMain game = null;
|
||||
#if !DEBUG
|
||||
try
|
||||
{
|
||||
#endif
|
||||
SteamManager.Initialize();
|
||||
game = new GameMain(args);
|
||||
#if !DEBUG
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (game != null) game.Dispose();
|
||||
CrashDump(null, "crashreport.log", e);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
game.Run();
|
||||
#else
|
||||
bool attemptRestart = false;
|
||||
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
game.Run();
|
||||
attemptRestart = false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (restartAttempts < 5 && CheckException(game, e))
|
||||
{
|
||||
attemptRestart = true;
|
||||
restartAttempts++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CrashDump(game, "crashreport.log", e);
|
||||
attemptRestart = false;
|
||||
}
|
||||
|
||||
}
|
||||
} while (attemptRestart);
|
||||
#endif
|
||||
|
||||
#if !DEBUG
|
||||
try
|
||||
{
|
||||
#endif
|
||||
game.Run();
|
||||
game.Dispose();
|
||||
#if !DEBUG
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
CrashDump(null, "crashreport.log", e);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static bool CheckException(GameMain game, Exception e)
|
||||
{
|
||||
#if WINDOWS
|
||||
|
||||
if (e is SharpDX.SharpDXException sharpDxException)
|
||||
{
|
||||
DebugConsole.NewMessage("SharpDX exception caught. ("
|
||||
+ e.Message + ", " + sharpDxException.ResultCode.Code.ToString("X") + "). Attempting to fix...", Microsoft.Xna.Framework.Color.Red);
|
||||
|
||||
switch ((UInt32)sharpDxException.ResultCode.Code)
|
||||
try
|
||||
{
|
||||
case 0x887A0022: //DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|
||||
switch (restartAttempts)
|
||||
{
|
||||
case 0:
|
||||
//just wait and try again
|
||||
DebugConsole.NewMessage("Retrying after 100 ms...", Microsoft.Xna.Framework.Color.Red);
|
||||
System.Threading.Thread.Sleep(100);
|
||||
return true;
|
||||
case 1:
|
||||
//force focus to this window
|
||||
DebugConsole.NewMessage("Forcing focus to the window and retrying...", Microsoft.Xna.Framework.Color.Red);
|
||||
var myForm = (Form)Control.FromHandle(game.Window.Handle);
|
||||
myForm.Focus();
|
||||
return true;
|
||||
case 2:
|
||||
//try disabling hardware mode switch
|
||||
if (GameMain.Config.WindowMode == WindowMode.Fullscreen)
|
||||
{
|
||||
DebugConsole.NewMessage("Failed to set fullscreen mode, switching configuration to borderless windowed.", Microsoft.Xna.Framework.Color.Red);
|
||||
GameMain.Config.WindowMode = WindowMode.BorderlessWindowed;
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
DebugConsole.NewMessage("Failed to resolve the DXGI_ERROR_NOT_CURRENTLY_AVAILABLE exception. Give up and let it crash :(", Microsoft.Xna.Framework.Color.Red);
|
||||
return false;
|
||||
|
||||
}
|
||||
case 0x80070057: //E_INVALIDARG/Invalid Arguments
|
||||
DebugConsole.NewMessage("Invalid graphics settings, attempting to fix...", Microsoft.Xna.Framework.Color.Red);
|
||||
|
||||
GameMain.Config.GraphicsWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
|
||||
GameMain.Config.GraphicsHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
|
||||
|
||||
DebugConsole.NewMessage("Display size set to " + GameMain.Config.GraphicsWidth + "x" + GameMain.Config.GraphicsHeight, Microsoft.Xna.Framework.Color.Red);
|
||||
|
||||
game.ApplyGraphicsSettings();
|
||||
|
||||
return true;
|
||||
default:
|
||||
DebugConsole.NewMessage("Unknown SharpDX exception code (" + sharpDxException.ResultCode.Code.ToString("X") + ")", Microsoft.Xna.Framework.Color.Red);
|
||||
return false;
|
||||
CrashDump(game, "crashreport.log", e);
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
CrashMessageBox("Barotrauma seems to have crashed, and failed to generate a crash report: "
|
||||
+ e2.Message + "\n" + e2.StackTrace.ToString(),
|
||||
null);
|
||||
}
|
||||
game?.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void CrashMessageBox(string message, string filePath)
|
||||
{
|
||||
#if WINDOWS
|
||||
MessageBox.Show(message, "Oops! Barotrauma just crashed.", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
#endif
|
||||
Microsoft.Xna.Framework.MessageBox.ShowWrapped(Microsoft.Xna.Framework.MessageBox.Flags.Error, "Oops! Barotrauma just crashed.", message);
|
||||
|
||||
// Open the crash log.
|
||||
Process.Start(filePath);
|
||||
if (!string.IsNullOrWhiteSpace(filePath)) { Process.Start(filePath); }
|
||||
}
|
||||
|
||||
static void CrashDump(GameMain game, string filePath, Exception exception)
|
||||
@@ -259,10 +164,18 @@ namespace Barotrauma
|
||||
|
||||
sb.AppendLine("\n");
|
||||
sb.AppendLine("Exception: " + exception.Message);
|
||||
#if WINDOWS
|
||||
if (exception is SharpDXException sharpDxException && ((uint)sharpDxException.HResult) == 0x887A0005)
|
||||
{
|
||||
var dxDevice = (SharpDX.Direct3D11.Device)game.GraphicsDevice.Handle;
|
||||
sb.AppendLine("Device removed reason: " + dxDevice.DeviceRemovedReason.ToString());
|
||||
}
|
||||
#endif
|
||||
if (exception.TargetSite != null)
|
||||
{
|
||||
sb.AppendLine("Target site: " + exception.TargetSite.ToString());
|
||||
}
|
||||
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.StackTrace);
|
||||
sb.AppendLine("\n");
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
string savePath = SaveUtil.CreateSavePath(isMultiplayer ? SaveUtil.SaveType.Multiplayer : SaveUtil.SaveType.Singleplayer, saveNameBox.Text);
|
||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackages.All(cp => GameMain.SelectedPackages.Any(cp2 => cp2.Name == cp));
|
||||
bool hasRequiredContentPackages = selectedSub.RequiredContentPackagesInstalled;
|
||||
|
||||
if (selectedSub.HasTag(SubmarineTag.Shuttle) || !hasRequiredContentPackages)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Barotrauma
|
||||
private GUIComponent selectedLocationInfo;
|
||||
private GUIListBox selectedMissionInfo;
|
||||
|
||||
private GUIButton repairHullsButton, repairItemsButton;
|
||||
private GUIButton repairHullsButton, replaceShuttlesButton, repairItemsButton;
|
||||
|
||||
private GUIFrame characterPreviewFrame;
|
||||
|
||||
@@ -281,6 +281,8 @@ namespace Barotrauma
|
||||
TextGetter = GetMoney
|
||||
};
|
||||
|
||||
// repair hulls -----------------------------------------------
|
||||
|
||||
var repairHullsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), repairContent.RectTransform), childAnchor: Anchor.TopRight)
|
||||
{
|
||||
RelativeSpacing = 0.05f,
|
||||
@@ -295,7 +297,7 @@ namespace Barotrauma
|
||||
{
|
||||
ForceUpperCase = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairHullsHolder.RectTransform), "500", textAlignment: Alignment.Right, font: GUI.LargeFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairHullsHolder.RectTransform), CampaignMode.HullRepairCost.ToString(), textAlignment: Alignment.Right, font: GUI.LargeFont);
|
||||
repairHullsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairHullsHolder.RectTransform), TextManager.Get("Repair"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
@@ -324,6 +326,8 @@ namespace Barotrauma
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
// repair items -------------------------------------------
|
||||
|
||||
var repairItemsHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), repairContent.RectTransform), childAnchor: Anchor.TopRight)
|
||||
{
|
||||
RelativeSpacing = 0.05f,
|
||||
@@ -338,7 +342,7 @@ namespace Barotrauma
|
||||
{
|
||||
ForceUpperCase = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairItemsHolder.RectTransform), "500", textAlignment: Alignment.Right, font: GUI.LargeFont);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), repairItemsHolder.RectTransform), CampaignMode.ItemRepairCost.ToString(), textAlignment: Alignment.Right, font: GUI.LargeFont);
|
||||
repairItemsButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), repairItemsHolder.RectTransform), TextManager.Get("Repair"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
@@ -367,6 +371,59 @@ namespace Barotrauma
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
// replace lost shuttles -------------------------------------------
|
||||
|
||||
var replaceShuttlesHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), repairContent.RectTransform), childAnchor: Anchor.TopRight)
|
||||
{
|
||||
RelativeSpacing = 0.05f,
|
||||
Stretch = true
|
||||
};
|
||||
new GUIImage(new RectTransform(new Vector2(0.3f, 1.0f), replaceShuttlesHolder.RectTransform, Anchor.CenterLeft), "ReplaceShuttlesButton")
|
||||
{
|
||||
IgnoreLayoutGroups = true,
|
||||
CanBeFocused = false
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), replaceShuttlesHolder.RectTransform), TextManager.Get("ReplaceLostShuttles"), textAlignment: Alignment.Right, font: GUI.LargeFont)
|
||||
{
|
||||
ForceUpperCase = true
|
||||
};
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.3f), replaceShuttlesHolder.RectTransform), CampaignMode.ShuttleReplaceCost.ToString(), textAlignment: Alignment.Right, font: GUI.LargeFont);
|
||||
replaceShuttlesButton = new GUIButton(new RectTransform(new Vector2(0.4f, 0.3f), replaceShuttlesHolder.RectTransform), TextManager.Get("ReplaceShuttles"), style: "GUIButtonLarge")
|
||||
{
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
if (GameMain.GameSession?.Submarine != null &&
|
||||
GameMain.GameSession.Submarine.LeftBehindSubDockingPortOccupied)
|
||||
{
|
||||
new GUIMessageBox("", TextManager.Get("ReplaceShuttleDockingPortOccupied"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (campaign.PurchasedLostShuttles)
|
||||
{
|
||||
campaign.Money += CampaignMode.ShuttleReplaceCost;
|
||||
campaign.PurchasedLostShuttles = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (campaign.Money >= CampaignMode.ShuttleReplaceCost)
|
||||
{
|
||||
campaign.Money -= CampaignMode.ShuttleReplaceCost;
|
||||
campaign.PurchasedLostShuttles = true;
|
||||
}
|
||||
}
|
||||
GameMain.Client?.SendCampaignState();
|
||||
btn.GetChild<GUITickBox>().Selected = campaign.PurchasedLostShuttles;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
new GUITickBox(new RectTransform(new Vector2(0.65f), replaceShuttlesButton.RectTransform, Anchor.CenterLeft) { AbsoluteOffset = new Point(10, 0) }, "")
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
|
||||
// mission info -------------------------------------------------------------------------
|
||||
|
||||
missionPanel = new GUIFrame(new RectTransform(new Vector2(0.3f, 0.5f), container.RectTransform, Anchor.TopRight)
|
||||
@@ -853,6 +910,19 @@ namespace Barotrauma
|
||||
(Campaign.PurchasedItemRepairs || Campaign.Money >= CampaignMode.ItemRepairCost) &&
|
||||
(GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign));
|
||||
repairItemsButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedItemRepairs;
|
||||
|
||||
if (GameMain.GameSession?.Submarine == null || !GameMain.GameSession.Submarine.SubsLeftBehind)
|
||||
{
|
||||
replaceShuttlesButton.Enabled = false;
|
||||
replaceShuttlesButton.GetChild<GUITickBox>().Selected = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
replaceShuttlesButton.Enabled =
|
||||
(Campaign.PurchasedLostShuttles || Campaign.Money >= CampaignMode.ShuttleReplaceCost) &&
|
||||
(GameMain.Client == null || GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign));
|
||||
replaceShuttlesButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedLostShuttles;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1308
Barotrauma/BarotraumaClient/Source/Screens/CharacterEditor/Wizard.cs
Normal file
1308
Barotrauma/BarotraumaClient/Source/Screens/CharacterEditor/Wizard.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,7 @@ namespace Barotrauma
|
||||
GameMain.Instance.OnResolutionChanged += () => { ClearChildren(); Load(); };
|
||||
|
||||
var doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null) { return; }
|
||||
configElement = doc.Root;
|
||||
|
||||
Load();
|
||||
@@ -34,126 +35,17 @@ namespace Barotrauma
|
||||
|
||||
foreach (XElement subElement in configElement.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "text":
|
||||
AddTextElement(subElement, listBox.Content.RectTransform);
|
||||
break;
|
||||
case "gridtext":
|
||||
AddGridTextElement(subElement, listBox.Content.RectTransform);
|
||||
break;
|
||||
case "spacing":
|
||||
AddSpacingElement(subElement, listBox.Content.RectTransform);
|
||||
break;
|
||||
case "image":
|
||||
AddImageElement(subElement, listBox.Content.RectTransform);
|
||||
break;
|
||||
}
|
||||
GUIComponent.FromXML(subElement, listBox.Content.RectTransform);
|
||||
}
|
||||
foreach (GUIComponent child in listBox.Children)
|
||||
{
|
||||
child.CanBeFocused = false;
|
||||
}
|
||||
|
||||
listBox.RecalculateChildren();
|
||||
listBox.UpdateScrollBarSize();
|
||||
}
|
||||
|
||||
private GUIComponent AddTextElement(XElement element, RectTransform parent, string overrideText = null, Anchor anchor = Anchor.Center)
|
||||
{
|
||||
var text = overrideText ?? element.ElementInnerText().Replace(@"\n", "\n");
|
||||
Color color = element.GetAttributeColor("color", Color.White);
|
||||
float scale = element.GetAttributeFloat("scale", 1.0f);
|
||||
Alignment alignment = Alignment.Center;
|
||||
Enum.TryParse(element.GetAttributeString("alignment", "Center"), out alignment);
|
||||
ScalableFont font = GUI.Font;
|
||||
switch (element.GetAttributeString("font", "Font").ToLowerInvariant())
|
||||
{
|
||||
case "font":
|
||||
font = GUI.Font;
|
||||
break;
|
||||
case "smallfont":
|
||||
font = GUI.SmallFont;
|
||||
break;
|
||||
case "largefont":
|
||||
font = GUI.LargeFont;
|
||||
break;
|
||||
case "videotitlefont":
|
||||
font = GUI.VideoTitleFont;
|
||||
break;
|
||||
case "objectivetitlefont":
|
||||
font = GUI.ObjectiveTitleFont;
|
||||
break;
|
||||
case "objectivenamefont":
|
||||
font = GUI.ObjectiveNameFont;
|
||||
break;
|
||||
}
|
||||
|
||||
var textHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), parent), style: null);
|
||||
var textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), textHolder.RectTransform, anchor),
|
||||
text,
|
||||
color,
|
||||
font,
|
||||
alignment,
|
||||
wrap: true)
|
||||
{
|
||||
TextScale = scale
|
||||
};
|
||||
textBlock.RectTransform.IsFixedSize = textHolder.RectTransform.IsFixedSize = true;
|
||||
textBlock.RectTransform.NonScaledSize = new Point(textBlock.Rect.Width, textBlock.Rect.Height);
|
||||
textHolder.RectTransform.NonScaledSize = new Point(textHolder.Rect.Width, textBlock.Rect.Height);
|
||||
return textHolder;
|
||||
}
|
||||
|
||||
private void AddGridTextElement(XElement element, RectTransform parent)
|
||||
{
|
||||
var text = element.ElementInnerText().Replace(@"\n", "\n");
|
||||
string[] elements = text.Split(',');
|
||||
RectTransform lineContainer = null;
|
||||
for (int i = 0; i < elements.Length; i++)
|
||||
{
|
||||
switch (i % 3)
|
||||
{
|
||||
case 0:
|
||||
lineContainer = AddTextElement(element, parent, elements[i], Anchor.CenterLeft).RectTransform;
|
||||
lineContainer.Anchor = Anchor.TopCenter;
|
||||
lineContainer.Pivot = Pivot.TopCenter;
|
||||
lineContainer.NonScaledSize = new Point((int)(parent.NonScaledSize.X * 0.7f), lineContainer.NonScaledSize.Y);
|
||||
break;
|
||||
case 1:
|
||||
AddTextElement(element, lineContainer, elements[i], Anchor.Center).GetChild<GUITextBlock>().TextAlignment = Alignment.Center;
|
||||
break;
|
||||
case 2:
|
||||
AddTextElement(element, lineContainer, elements[i], Anchor.CenterRight).GetChild<GUITextBlock>().TextAlignment = Alignment.CenterRight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSpacingElement(XElement element, RectTransform parent)
|
||||
{
|
||||
if (element.Attribute("absoluteheight") != null)
|
||||
{
|
||||
int absoluteHeight = element.GetAttributeInt("absoluteheight", 10);
|
||||
var textHolder = new GUIFrame(new RectTransform(new Point(parent.NonScaledSize.X, absoluteHeight), parent), style: null);
|
||||
}
|
||||
else
|
||||
{
|
||||
float relativeHeight = element.GetAttributeFloat("relativeheight", 0.0f);
|
||||
var textHolder = new GUIFrame(new RectTransform(new Vector2(1.0f, relativeHeight), parent), style: null);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddImageElement(XElement element, RectTransform parent)
|
||||
{
|
||||
Sprite sprite = new Sprite(element);
|
||||
|
||||
if (element.Attribute("absoluteheight") != null)
|
||||
{
|
||||
int absoluteHeight = element.GetAttributeInt("absoluteheight", 10);
|
||||
new GUIImage(new RectTransform(new Point(parent.NonScaledSize.X, absoluteHeight), parent), sprite, scaleToFit: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
float relativeHeight = element.GetAttributeFloat("relativeheight", 0.0f);
|
||||
new GUIImage(new RectTransform(new Vector2(1.0f, relativeHeight), parent), sprite, scaleToFit: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
listBox.BarScroll = 0.0f;
|
||||
|
||||
@@ -501,7 +501,7 @@ namespace Barotrauma
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelGenerationParameters))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
if (doc == null) { continue; }
|
||||
|
||||
foreach (LevelGenerationParams genParams in LevelGenerationParams.LevelParams)
|
||||
{
|
||||
@@ -523,7 +523,7 @@ namespace Barotrauma
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
if (doc == null) { continue; }
|
||||
|
||||
foreach (LevelObjectPrefab levelObjPrefab in LevelObjectPrefab.List)
|
||||
{
|
||||
@@ -549,7 +549,7 @@ namespace Barotrauma
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelGenerationParameters))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
if (doc == null) { continue; }
|
||||
|
||||
bool elementFound = false;
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
@@ -664,7 +664,7 @@ namespace Barotrauma
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.LevelObjectPrefabs))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc?.Root == null) continue;
|
||||
if (doc == null) { continue; }
|
||||
var newElement = new XElement(newPrefab.Name);
|
||||
newPrefab.Save(newElement);
|
||||
newElement.Add(new XElement("Sprite",
|
||||
|
||||
@@ -4,10 +4,12 @@ using Barotrauma.Tutorials;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -68,6 +70,16 @@ namespace Barotrauma
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
FetchRemoteContent(Frame.RectTransform);
|
||||
/*var doc = XMLExtensions.TryLoadXml("Content/UI/MenuTextTest.xml");
|
||||
if (doc?.Root != null)
|
||||
{
|
||||
foreach (XElement subElement in doc?.Root.Elements())
|
||||
{
|
||||
GUIComponent.FromXML(subElement, Frame.RectTransform);
|
||||
}
|
||||
}*/
|
||||
|
||||
// === CAMPAIGN
|
||||
var campaignHolder = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 1.0f), parent: buttonsParent.RectTransform) { RelativeOffset = new Vector2(0.1f, 0.0f) }, isHorizontal: true);
|
||||
|
||||
@@ -360,6 +372,7 @@ namespace Barotrauma
|
||||
{
|
||||
OnClicked = SelectTab
|
||||
};
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -506,7 +519,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
titleText.Visible = true;
|
||||
selectedTab = 0;
|
||||
}
|
||||
|
||||
@@ -575,7 +589,7 @@ namespace Barotrauma
|
||||
//(gamesession.GameMode as SinglePlayerCampaign).GenerateMap(ToolBox.RandomSeed(8));
|
||||
gamesession.StartRound(ToolBox.RandomSeed(8));
|
||||
GameMain.GameScreen.Select();
|
||||
|
||||
// TODO: modding support
|
||||
string[] jobIdentifiers = new string[] { "captain", "engineer", "mechanic" };
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
@@ -587,14 +601,14 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
var characterInfo = new CharacterInfo(
|
||||
Character.HumanConfigFile,
|
||||
jobPrefab: JobPrefab.List.Find(j => j.Identifier == jobIdentifiers[i]));
|
||||
Character.HumanSpeciesName,
|
||||
jobPrefab: JobPrefab.Get(jobIdentifiers[i]));
|
||||
if (characterInfo.Job == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to find the job \"" + jobIdentifiers[i] + "\"!");
|
||||
}
|
||||
|
||||
var newCharacter = Character.Create(Character.HumanConfigFile, spawnPoint.WorldPosition, ToolBox.RandomSeed(8), characterInfo);
|
||||
var newCharacter = Character.Create(Character.HumanSpeciesName, spawnPoint.WorldPosition, ToolBox.RandomSeed(8), characterInfo);
|
||||
newCharacter.GiveJobItems(spawnPoint);
|
||||
gamesession.CrewManager.AddCharacter(newCharacter);
|
||||
Character.Controlled = newCharacter;
|
||||
@@ -872,7 +886,7 @@ namespace Barotrauma
|
||||
GUI.DrawLine(spriteBatch, textPos, textPos - Vector2.UnitX * textSize.X, mouseOn ? Color.White : Color.White * 0.7f);
|
||||
if (mouseOn && PlayerInput.LeftButtonClicked())
|
||||
{
|
||||
Process.Start("http://privacypolicy.daedalic.com");
|
||||
GameMain.Instance.ShowOpenUrlInWebBrowserPrompt("http://privacypolicy.daedalic.com");
|
||||
}
|
||||
}
|
||||
textPos.Y -= textSize.Y;
|
||||
@@ -955,7 +969,7 @@ namespace Barotrauma
|
||||
if (File.Exists(ServerSettings.SettingsFile))
|
||||
{
|
||||
XDocument settingsDoc = XMLExtensions.TryLoadXml(ServerSettings.SettingsFile);
|
||||
if (settingsDoc?.Root != null)
|
||||
if (settingsDoc != null)
|
||||
{
|
||||
port = settingsDoc.Root.GetAttributeInt("port", port);
|
||||
queryPort = settingsDoc.Root.GetAttributeInt("queryport", queryPort);
|
||||
@@ -1050,7 +1064,47 @@ namespace Barotrauma
|
||||
OnClicked = HostServerClicked
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
private void FetchRemoteContent(RectTransform parent)
|
||||
{
|
||||
if (string.IsNullOrEmpty(GameMain.Config.RemoteContentUrl)) { return; }
|
||||
try
|
||||
{
|
||||
var client = new RestClient(GameMain.Config.RemoteContentUrl);
|
||||
var request = new RestRequest("MenuContent.xml", Method.GET);
|
||||
|
||||
IRestResponse response = client.Execute(request);
|
||||
if (response.ResponseStatus != ResponseStatus.Completed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string xml = response.Content;
|
||||
int index = xml.IndexOf('<');
|
||||
if (index > 0) { xml = xml.Substring(index, xml.Length - index); }
|
||||
if (string.IsNullOrWhiteSpace(xml)) { return; }
|
||||
|
||||
XElement element = XDocument.Parse(xml)?.Root;
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
GUIComponent.FromXML(subElement, parent);
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError("Fetching remote content to the main menu failed.", e);
|
||||
#endif
|
||||
GameAnalyticsManager.AddErrorEventOnce("MainMenuScreen.FetchRemoteContent:Exception", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Fetching remote content to the main menu failed. " + e.Message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,11 +449,7 @@ namespace Barotrauma
|
||||
{
|
||||
UserData = mode
|
||||
};
|
||||
//TODO: translate mission descriptions
|
||||
if (TextManager.Language == "English")
|
||||
{
|
||||
textBlock.ToolTip = mode.Description;
|
||||
}
|
||||
textBlock.ToolTip = mode.Description;
|
||||
}
|
||||
|
||||
//mission type ------------------------------------------------------------------
|
||||
@@ -731,7 +727,7 @@ namespace Barotrauma
|
||||
ReadyToStartBox.Selected = false;
|
||||
if (campaignUI != null)
|
||||
{
|
||||
//SelectTab(Tab.Map);
|
||||
campaignUI.SelectTab(CampaignUI.Tab.Map);
|
||||
if (campaignUI.StartButton != null)
|
||||
{
|
||||
campaignUI.StartButton.Visible = !GameMain.Client.GameStarted &&
|
||||
@@ -909,7 +905,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (characterInfo == null)
|
||||
{
|
||||
characterInfo = new CharacterInfo(Character.HumanConfigFile, GameMain.NetworkMember.Name, null);
|
||||
characterInfo = new CharacterInfo(Character.HumanSpeciesName, GameMain.Client.Name, null);
|
||||
characterInfo.RecreateHead(
|
||||
GameMain.Config.CharacterHeadIndex,
|
||||
GameMain.Config.CharacterRace,
|
||||
@@ -930,7 +926,7 @@ namespace Barotrauma
|
||||
UserData = characterInfo
|
||||
};
|
||||
|
||||
CharacterNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), infoContainer.RectTransform), characterInfo.Name, font: GUI.LargeFont, textAlignment: Alignment.Center)
|
||||
CharacterNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.1f), infoContainer.RectTransform), characterInfo.Name, textAlignment: Alignment.Center)
|
||||
{
|
||||
MaxTextLength = Client.MaxNameLength,
|
||||
OverflowClip = true
|
||||
@@ -947,7 +943,7 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
ReadyToStartBox.Selected = false;
|
||||
GameMain.Client.Name = tb.Text;
|
||||
GameMain.Client.SetName(tb.Text);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1011,7 +1007,7 @@ namespace Barotrauma
|
||||
int i = 1;
|
||||
foreach (string jobIdentifier in GameMain.Config.JobPreferences)
|
||||
{
|
||||
JobPrefab job = JobPrefab.List.Find(j => j.Identifier == jobIdentifier);
|
||||
if (!JobPrefab.List.TryGetValue(jobIdentifier, out JobPrefab job)) { continue; }
|
||||
if (job == null || job.MaxNumber <= 0) continue;
|
||||
|
||||
var jobFrame = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.2f), jobList.Content.RectTransform) { MinSize = new Point(0, 20) }, style: "ListBoxElement")
|
||||
@@ -1247,6 +1243,12 @@ namespace Barotrauma
|
||||
};
|
||||
}
|
||||
|
||||
if (!sub.RequiredContentPackagesInstalled)
|
||||
{
|
||||
subTextBlock.TextColor = Color.Lerp(subTextBlock.TextColor, Color.DarkRed, 0.5f);
|
||||
frame.ToolTip = TextManager.Get("ContentPackageMismatch") + "\n\n" + frame.ToolTip;
|
||||
}
|
||||
|
||||
if (sub.HasTag(SubmarineTag.Shuttle))
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), frame.RectTransform, Anchor.CenterRight) { RelativeOffset = new Vector2(0.1f, 0.0f) },
|
||||
@@ -1270,14 +1272,32 @@ namespace Barotrauma
|
||||
|
||||
public bool VotableClicked(GUIComponent component, object userData)
|
||||
{
|
||||
if (GameMain.Client == null) return false;
|
||||
if (GameMain.Client == null) { return false; }
|
||||
|
||||
VoteType voteType;
|
||||
if (component.Parent == GameMain.NetLobbyScreen.SubList.Content)
|
||||
{
|
||||
if (!GameMain.Client.ServerSettings.Voting.AllowSubVoting)
|
||||
{
|
||||
if (GameMain.Client.HasPermission(ClientPermissions.SelectSub))
|
||||
var selectedSub = component.UserData as Submarine;
|
||||
if (!selectedSub.RequiredContentPackagesInstalled)
|
||||
{
|
||||
var msgBox = new GUIMessageBox(TextManager.Get("ContentPackageMismatch"),
|
||||
selectedSub.RequiredContentPackages.Any() ?
|
||||
TextManager.GetWithVariable("ContentPackageMismatchWarning", "[requiredcontentpackages]", string.Join(", ", selectedSub.RequiredContentPackages)) :
|
||||
TextManager.Get("ContentPackageMismatchWarningGeneric"),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
msgBox.Buttons[0].OnClicked = msgBox.Close;
|
||||
msgBox.Buttons[0].OnClicked += (button, obj) =>
|
||||
{
|
||||
GameMain.Client.RequestSelectSub(component.Parent.GetChildIndex(component), isShuttle: false);
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
return false;
|
||||
}
|
||||
else if (GameMain.Client.HasPermission(ClientPermissions.SelectSub))
|
||||
{
|
||||
GameMain.Client.RequestSelectSub(component.Parent.GetChildIndex(component), isShuttle: false);
|
||||
return true;
|
||||
@@ -1714,16 +1734,6 @@ namespace Barotrauma
|
||||
jobInfoFrame?.AddToGUIUpdateList();
|
||||
}
|
||||
|
||||
public List<Submarine> GetSubList()
|
||||
{
|
||||
List<Submarine> subs = new List<Submarine>();
|
||||
foreach (GUIComponent component in subList.Content.Children)
|
||||
{
|
||||
if (component.UserData is Submarine) subs.Add((Submarine)component.UserData);
|
||||
}
|
||||
|
||||
return subs;
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
@@ -2057,7 +2067,7 @@ namespace Barotrauma
|
||||
.UserData as Submarine;
|
||||
|
||||
//matching sub found and already selected, all good
|
||||
if (sub != null && subList.SelectedData is Submarine selectedSub && selectedSub.MD5Hash?.Hash == md5Hash)
|
||||
if (sub != null && subList.SelectedData is Submarine selectedSub && selectedSub.MD5Hash?.Hash == md5Hash && System.IO.File.Exists(sub.FilePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -2090,12 +2100,12 @@ namespace Barotrauma
|
||||
FailedSelectedShuttle = null;
|
||||
|
||||
//hashes match, all good
|
||||
if (sub.MD5Hash?.Hash == md5Hash)
|
||||
if (sub.MD5Hash?.Hash == md5Hash && Submarine.SavedSubmarines.Contains(sub))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
//if we get to this point, a matching sub was not found or it has an incorrect MD5 hash
|
||||
|
||||
@@ -2105,14 +2115,15 @@ namespace Barotrauma
|
||||
FailedSelectedShuttle = new Pair<string, string>(subName, md5Hash);
|
||||
|
||||
string errorMsg = "";
|
||||
if (sub == null)
|
||||
if (sub == null || !Submarine.SavedSubmarines.Contains(sub))
|
||||
{
|
||||
errorMsg = TextManager.GetWithVariable("SubNotFoundError", "[subname]", subName) + " ";
|
||||
}
|
||||
else if (sub.MD5Hash?.Hash == null)
|
||||
{
|
||||
errorMsg = TextManager.GetWithVariable("SubLoadError", "[subname]", subName) + " ";
|
||||
subList.Content.GetChildByUserData(sub).GetChild<GUITextBox>().TextColor = Color.Red;
|
||||
GUITextBlock textBlock = subList.Content.GetChildByUserData(sub)?.GetChild<GUITextBlock>();
|
||||
if (textBlock != null) { textBlock.TextColor = Color.Red; }
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace Barotrauma
|
||||
foreach (string configFile in GameMain.Instance.GetFilesOfType(ContentType.Particles))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(configFile);
|
||||
if (doc == null || doc.Root == null) continue;
|
||||
if (doc == null) { continue; }
|
||||
|
||||
var prefabList = GameMain.ParticleManager.GetPrefabList();
|
||||
foreach (ParticlePrefab prefab in prefabList)
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Barotrauma
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), clientNameHolder.RectTransform), TextManager.Get("YourName"));
|
||||
clientNameBox = new GUITextBox(new RectTransform(new Vector2(1.0f, 0.5f), clientNameHolder.RectTransform), "")
|
||||
{
|
||||
Text = GameMain.Config.DefaultPlayerName,
|
||||
Text = GameMain.Config.PlayerName,
|
||||
MaxTextLength = Client.MaxNameLength,
|
||||
OverflowClip = true
|
||||
};
|
||||
@@ -822,11 +822,20 @@ namespace Barotrauma
|
||||
|
||||
private void ServerQueryFinished()
|
||||
{
|
||||
if (serverList.Content.Children.All(c => !c.Visible))
|
||||
if (!serverList.Content.Children.Any())
|
||||
{
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), serverList.Content.RectTransform),
|
||||
TextManager.Get("NoMatchingServers"))
|
||||
new GUITextBlock(new RectTransform(Vector2.One, serverList.Content.RectTransform),
|
||||
TextManager.Get("NoServers"), textAlignment: Alignment.Center)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
}
|
||||
else if (serverList.Content.Children.All(c => !c.Visible))
|
||||
{
|
||||
new GUITextBlock(new RectTransform(Vector2.One, serverList.Content.RectTransform),
|
||||
TextManager.Get("NoMatchingServers"), textAlignment: Alignment.Center)
|
||||
{
|
||||
CanBeFocused = false,
|
||||
UserData = "noresults"
|
||||
};
|
||||
}
|
||||
@@ -918,7 +927,7 @@ namespace Barotrauma
|
||||
return false;
|
||||
}
|
||||
|
||||
GameMain.Config.DefaultPlayerName = clientNameBox.Text;
|
||||
GameMain.Config.PlayerName = clientNameBox.Text;
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
|
||||
CoroutineManager.StartCoroutine(ConnectToServer(ip, serverName));
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace Barotrauma
|
||||
if (file.Path.EndsWith(".xml"))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(file.Path);
|
||||
if (doc != null && doc.Root != null)
|
||||
if (doc != null)
|
||||
{
|
||||
LoadSprites(doc.Root);
|
||||
}
|
||||
|
||||
@@ -164,8 +164,7 @@ namespace Barotrauma
|
||||
if (userdata is Facepunch.Steamworks.Workshop.Item item)
|
||||
{
|
||||
if (!item.Installed) { return false; }
|
||||
CreateWorkshopItem(item);
|
||||
ShowCreateItemFrame();
|
||||
if (CreateWorkshopItem(item)) { ShowCreateItemFrame(); }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -310,7 +309,7 @@ namespace Barotrauma
|
||||
CreateMyItemFrame(contentPackage, myItemList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnItemsReceived(IList<Facepunch.Steamworks.Workshop.Item> itemDetails, GUIListBox listBox)
|
||||
{
|
||||
listBox.ClearChildren();
|
||||
@@ -525,6 +524,9 @@ namespace Barotrauma
|
||||
OnClicked = DownloadItem
|
||||
};
|
||||
}
|
||||
|
||||
innerFrame.Recalculate();
|
||||
listBox.RecalculateChildren();
|
||||
}
|
||||
|
||||
private void RemoveItemFromLists(ulong itemID)
|
||||
@@ -651,6 +653,9 @@ namespace Barotrauma
|
||||
{
|
||||
if (!(tickBox.UserData is Facepunch.Steamworks.Workshop.Item item)) { return false; }
|
||||
|
||||
//currently editing the item, don't allow enabling/disabling it
|
||||
if (itemEditor?.Id == item.Id) { tickBox.Selected = true; return false; }
|
||||
|
||||
var updateButton = tickBox.Parent.FindChild("updatebutton");
|
||||
|
||||
string errorMsg = "";
|
||||
@@ -724,23 +729,30 @@ namespace Barotrauma
|
||||
}
|
||||
};
|
||||
|
||||
var headerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform)) { Color = Color.Black };
|
||||
var centerArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.5f), content.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
RelativeSpacing = 0.01f,
|
||||
Color = Color.Black * 0.9f
|
||||
};
|
||||
|
||||
if (itemPreviewSprites.ContainsKey(item.PreviewImageUrl))
|
||||
{
|
||||
new GUIImage(new RectTransform(Vector2.One, headerArea.RectTransform), itemPreviewSprites[item.PreviewImageUrl], scaleToFit: true);
|
||||
new GUIImage(new RectTransform(new Vector2(0.5f, 1.0f), centerArea.RectTransform), itemPreviewSprites[item.PreviewImageUrl], scaleToFit: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
new GUIImage(new RectTransform(Vector2.One, headerArea.RectTransform), SteamManager.Instance.DefaultPreviewImage, scaleToFit: true);
|
||||
new GUIImage(new RectTransform(new Vector2(0.5f, 0.0f), centerArea.RectTransform), SteamManager.Instance.DefaultPreviewImage, scaleToFit: true);
|
||||
}
|
||||
|
||||
var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.2f), content.RectTransform)) { ScrollBarVisible = true };
|
||||
var descriptionContainer = new GUIListBox(new RectTransform(new Vector2(0.5f, 1.0f), centerArea.RectTransform)) { ScrollBarVisible = true };
|
||||
|
||||
//spacing
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform) { MinSize = new Point(0, 5) }, style: null);
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform), TextManager.EnsureUTF8(item.Description), wrap: true)
|
||||
string description = TextManager.EnsureUTF8(item.Description);
|
||||
description = ToolBox.RemoveBBCodeTags(description);
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), descriptionContainer.Content.RectTransform), description, wrap: true)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
@@ -799,12 +811,24 @@ namespace Barotrauma
|
||||
|
||||
var modificationDate = new GUITextBlock(new RectTransform(new Vector2(0.7f, 0.0f), content.RectTransform), TextManager.Get("WorkshopItemModificationDate"));
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), modificationDate.RectTransform, Anchor.CenterRight), item.Modified.ToString("dd.MM.yyyy"), textAlignment: Alignment.TopRight);
|
||||
}
|
||||
|
||||
/*private void CreateWorkshopItem()
|
||||
{
|
||||
SteamManager.CreateWorkshopItemStaging("ModName", out itemEditor, out itemContentPackage);
|
||||
}*/
|
||||
if (item.Subscribed)
|
||||
{
|
||||
var buttonContainer = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.05f), content.RectTransform) { MinSize = new Point(0, 25) }, isHorizontal: true);
|
||||
new GUIButton(new RectTransform(new Vector2(0.5f, 0.95f), buttonContainer.RectTransform), TextManager.Get("WorkshopItemUnsubscribe"))
|
||||
{
|
||||
UserData = item,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
item.UnSubscribe();
|
||||
subscribedItemList.RemoveChild(subscribedItemList.Content.GetChildByUserData(item));
|
||||
itemPreviewFrame.ClearChildren();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateWorkshopItem(Submarine sub)
|
||||
{
|
||||
string destinationFolder = Path.Combine("Mods", sub.Name);
|
||||
@@ -826,7 +850,7 @@ namespace Barotrauma
|
||||
itemContentPackage.Name = sub.Name;
|
||||
itemContentPackage.Save(itemContentPackage.Path);
|
||||
ContentPackage.List.Add(itemContentPackage);
|
||||
GameMain.Config.SelectedContentPackages.Add(itemContentPackage);
|
||||
GameMain.Config.SelectContentPackage(itemContentPackage);
|
||||
|
||||
itemEditor.Title = sub.Name;
|
||||
itemEditor.Tags.Add("Submarine");
|
||||
@@ -886,15 +910,21 @@ namespace Barotrauma
|
||||
}*/
|
||||
|
||||
}
|
||||
private void CreateWorkshopItem(Facepunch.Steamworks.Workshop.Item item)
|
||||
private bool CreateWorkshopItem(Facepunch.Steamworks.Workshop.Item item)
|
||||
{
|
||||
if (!item.Installed)
|
||||
{
|
||||
new GUIMessageBox(TextManager.Get("Error"),
|
||||
new GUIMessageBox(TextManager.Get("Error"),
|
||||
TextManager.GetWithVariable("WorkshopErrorInstallRequiredToEdit", "[itemname]", TextManager.EnsureUTF8(item.Title)));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
SteamManager.CreateWorkshopItemStaging(item, out itemEditor, out itemContentPackage);
|
||||
if (!SteamManager.CreateWorkshopItemStaging(item, out itemEditor, out itemContentPackage))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var tickBox = publishedItemList.Content.GetChildByUserData(item)?.GetAnyChild<GUITickBox>();
|
||||
if (tickBox != null) { tickBox.Selected = true; }
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ShowCreateItemFrame()
|
||||
@@ -1256,6 +1286,14 @@ namespace Barotrauma
|
||||
createItemFileList.Flash(Color.Red);
|
||||
}
|
||||
|
||||
if (!itemContentPackage.CheckValidity(out List<string> errorMessages))
|
||||
{
|
||||
new GUIMessageBox(
|
||||
TextManager.GetWithVariable("workshopitempublishfailed", "[itemname]", itemEditor.Title),
|
||||
string.Join("\n", errorMessages));
|
||||
return false;
|
||||
}
|
||||
|
||||
PublishWorkshopItem();
|
||||
return true;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user