(3dc4135ce) v0.9.5.1

This commit is contained in:
Regalis
2019-11-21 18:22:25 +01:00
parent b39922a074
commit 5c95c53118
287 changed files with 12655 additions and 5048 deletions
@@ -14,10 +14,27 @@ namespace Barotrauma
Vector2 pos = Character.WorldPosition;
pos.Y = -pos.Y;
if (SelectedAiTarget?.Entity != null)
if (State == AIState.Idle && PreviousState == AIState.Attack)
{
GUI.DrawLine(spriteBatch, pos, new Vector2(SelectedAiTarget.WorldPosition.X, -SelectedAiTarget.WorldPosition.Y), Color.Red * 0.5f, 0, 4);
var target = _selectedAiTarget ?? _lastAiTarget;
if (target != null)
{
var memory = GetTargetMemory(target);
Vector2 targetPos = memory.Location;
targetPos.Y = -targetPos.Y;
GUI.DrawLine(spriteBatch, pos, targetPos, Color.White * 0.5f, 0, 4);
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{target.Entity.ToString()} ({memory.Priority.FormatZeroDecimal()})", Color.White, Color.Black);
}
}
else if (SelectedAiTarget?.Entity != null)
{
Vector2 targetPos = SelectedAiTarget.WorldPosition;
if (State == AIState.Attack)
{
targetPos = attackWorldPos;
}
targetPos.Y = -targetPos.Y;
GUI.DrawLine(spriteBatch, pos, targetPos, Color.Red * 0.5f, 0, 4);
if (wallTarget != null)
{
Vector2 wallTargetPos = wallTarget.Position;
@@ -26,7 +43,8 @@ namespace Barotrauma
GUI.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Orange, false);
GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5);
}
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity.ToString()} ({targetValue.FormatZeroDecimal()})", Color.Red, Color.Black);
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 60.0f, $"{SelectedAiTarget.Entity.ToString()} ({GetTargetMemory(SelectedAiTarget).Priority.FormatZeroDecimal()})", Color.Red, Color.Black);
GUI.DrawString(spriteBatch, pos - Vector2.UnitY * 40.0f, $"({targetValue.FormatZeroDecimal()})", Color.Red, Color.Black);
}
/*GUI.Font.DrawString(spriteBatch, targetValue.ToString(), pos - Vector2.UnitY * 80.0f, Color.Red);
@@ -42,6 +60,9 @@ namespace Barotrauma
case AIState.Escape:
stateColor = Color.LightBlue;
break;
case AIState.Flee:
stateColor = Color.White;
break;
case AIState.Eat:
stateColor = Color.Brown;
break;
@@ -59,8 +80,8 @@ namespace Barotrauma
if (LatchOntoAI.WallAttachPos.HasValue)
{
GUI.DrawLine(spriteBatch, pos,
ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.WallAttachPos.Value.X, -LatchOntoAI.WallAttachPos.Value.Y)), Color.Green, 0, 3);
//GUI.DrawLine(spriteBatch, pos,
// ConvertUnits.ToDisplayUnits(new Vector2(LatchOntoAI.WallAttachPos.Value.X, -LatchOntoAI.WallAttachPos.Value.Y)), Color.Green, 0, 3);
}
}
@@ -93,6 +114,17 @@ namespace Barotrauma
}
}
}
else
{
if (steeringManager.AvoidDir.LengthSquared() > 0.0001f)
{
Vector2 hitPos = ConvertUnits.ToDisplayUnits(steeringManager.AvoidRayCastHitPosition);
hitPos.Y = -hitPos.Y;
GUI.DrawLine(spriteBatch, hitPos, hitPos + new Vector2(steeringManager.AvoidDir.X, -steeringManager.AvoidDir.Y) * 100, Color.Red, width: 5);
//GUI.DrawLine(spriteBatch, pos, ConvertUnits.ToDisplayUnits(steeringManager.AvoidLookAheadPos.X, -steeringManager.AvoidLookAheadPos.Y), Color.Orange, width: 4);
}
}
GUI.DrawLine(spriteBatch, pos, pos + ConvertUnits.ToDisplayUnits(new Vector2(Character.AnimController.TargetMovement.X, -Character.AnimController.TargetMovement.Y)), Color.SteelBlue, width: 2);
GUI.DrawLine(spriteBatch, pos, pos + ConvertUnits.ToDisplayUnits(new Vector2(Steering.X, -Steering.Y)), Color.Blue, width: 3);
}
@@ -25,7 +25,7 @@ namespace Barotrauma
{
Vector2 pos = Character.WorldPosition;
pos.Y = -pos.Y;
Vector2 textOffset = new Vector2(-40, -120);
Vector2 textOffset = new Vector2(-40, -160);
if (SelectedAiTarget?.Entity != null)
{
@@ -33,26 +33,36 @@ namespace Barotrauma
//GUI.DrawString(spriteBatch, pos + textOffset, $"AI TARGET: {SelectedAiTarget.Entity.ToString()}", Color.White, Color.Black);
}
GUI.DrawString(spriteBatch, pos + textOffset, Character.Name, Color.White, Color.Black);
if (ObjectiveManager != null)
{
var currentOrder = ObjectiveManager.CurrentOrder;
if (currentOrder != null)
{
GUI.DrawString(spriteBatch, pos + textOffset, $"ORDER: {currentOrder.DebugTag} ({currentOrder.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20), $"ORDER: {currentOrder.DebugTag} ({currentOrder.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
}
else if (ObjectiveManager.WaitTimer > 0)
{
GUI.DrawString(spriteBatch, pos + textOffset, $"Waiting... {ObjectiveManager.WaitTimer.FormatZeroDecimal()}", Color.White, Color.Black);
GUI.DrawString(spriteBatch, pos + new Vector2(0, 20), $"Waiting... {ObjectiveManager.WaitTimer.FormatZeroDecimal()}", Color.White, Color.Black);
}
var currentObjective = ObjectiveManager.CurrentObjective;
if (currentObjective != null)
{
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20), $"OBJECTIVE: {currentObjective.DebugTag} ({currentObjective.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
if (currentOrder == null)
{
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 20), $"MAIN OBJECTIVE: {currentObjective.DebugTag} ({currentObjective.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
}
var subObjective = currentObjective.SubObjectives.FirstOrDefault();
if (subObjective != null)
{
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 40), $"SUBOBJECTIVE: {subObjective.DebugTag} ({subObjective.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
}
var activeObjective = ObjectiveManager.GetActiveObjective();
if (activeObjective != null)
{
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 60), $"ACTIVE OBJECTIVE: {activeObjective.DebugTag} ({activeObjective.GetPriority().FormatZeroDecimal()})", Color.White, Color.Black);
}
}
}
@@ -81,7 +91,7 @@ namespace Barotrauma
new Vector2(path.CurrentNode.DrawPosition.X, -path.CurrentNode.DrawPosition.Y),
Color.BlueViolet, 0, 3);
GUI.DrawString(spriteBatch, pos + textOffset - new Vector2(0, 20), "Path cost: " + path.Cost.FormatZeroDecimal(), Color.White, Color.Black * 0.5f);
GUI.DrawString(spriteBatch, pos + textOffset + new Vector2(0, 80), "Path cost: " + path.Cost.FormatZeroDecimal(), Color.White, Color.Black * 0.5f);
}
}
}
@@ -24,7 +24,7 @@ namespace Barotrauma
partial void UpdateNetPlayerPositionProjSpecific(float deltaTime, float lowestSubPos)
{
if (character != GameMain.Client.Character || !character.AllowInput)
if (character != GameMain.Client.Character || !character.CanMove)
{
//remove states without a timestamp (there may still be ID-based states
//in the list when the controlled character switches to timestamp-based interpolation)
@@ -92,10 +92,10 @@ namespace Barotrauma
Collider.AngularVelocity = newAngularVelocity;
float distSqrd = Vector2.DistanceSquared(newPosition, Collider.SimPosition);
float errorTolerance = character.AllowInput ? 0.01f : 0.2f;
float errorTolerance = character.CanMove ? 0.01f : 0.2f;
if (distSqrd > errorTolerance)
{
if (distSqrd > 10.0f || !character.AllowInput)
if (distSqrd > 10.0f || !character.CanMove)
{
Collider.TargetRotation = newRotation;
SetPosition(newPosition, lerp: distSqrd < 5.0f, ignorePlatforms: false);
@@ -108,9 +108,9 @@ namespace Barotrauma
}
}
//unconscious/dead characters can't correct their position using AnimController movement
//immobilized characters can't correct their position using AnimController movement
// -> we need to correct it manually
if (!character.AllowInput)
if (!character.CanMove)
{
float mainLimbDistSqrd = Vector2.DistanceSquared(MainLimb.PullJointWorldAnchorA, Collider.SimPosition);
float mainLimbErrorTolerance = 0.1f;
@@ -343,7 +343,7 @@ namespace Barotrauma
partial void OnAttackedProjSpecific(Character attacker, AttackResult attackResult)
{
if (attackResult.Damage <= 1.0f) { return; }
if (attackResult.Damage <= 1.0f || IsDead) { return; }
if (soundTimer < soundInterval * 0.5f)
{
PlaySound(CharacterSound.SoundType.Damage);
@@ -524,6 +524,8 @@ namespace Barotrauma
partial void UpdateProjSpecific(float deltaTime, Camera cam)
{
if (!enabled) { return; }
if (!IsDead && !IsUnconscious)
{
if (soundTimer > 0)
@@ -50,7 +50,7 @@ namespace Barotrauma
Job.Name, textColor: Job.Prefab.UIColor, font: font);
}
if (personalityTrait != null && TextManager.Language == "English")
if (personalityTrait != null)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), headerTextArea.RectTransform),
TextManager.AddPunctuation(':', TextManager.Get("PersonalityTrait"), TextManager.Get("personalitytrait." + personalityTrait.Name.Replace(" ", ""))), font: font);
@@ -125,7 +125,7 @@ namespace Barotrauma
}
}
partial void LoadAttachmentSprites()
partial void LoadAttachmentSprites(bool omitJob)
{
if (attachmentSprites == null)
{
@@ -139,7 +139,25 @@ namespace Barotrauma
BeardElement?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Beard)));
MoustacheElement?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Moustache)));
HairElement?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.Hair)));
Job?.Prefab.ClothingElement?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
if (omitJob)
{
JobPrefab.NoJobElement?.Element("PortraitClothing")?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
}
else
{
Job?.Prefab.ClothingElement?.Elements("sprite").ForEach(s => attachmentSprites.Add(new WearableSprite(s, WearableType.JobIndicator)));
}
}
// Doesn't work if the head's source rect does not start at 0,0.
public static Point CalculateOffset(Sprite sprite, Point offset) => sprite.SourceRect.Size * offset;
public void CalculateHeadPosition(Sprite sprite)
{
if (sprite == null) { return; }
if (Head.SheetIndex == null) { return; }
Point location = CalculateOffset(sprite, Head.SheetIndex.Value.ToPoint());
sprite.SourceRect = new Rectangle(location, sprite.SourceRect.Size);
}
public void DrawPortrait(SpriteBatch spriteBatch, Vector2 screenPos, float targetWidth)
@@ -155,6 +173,10 @@ namespace Barotrauma
// Scale down the head sprite 10%
float scale = targetWidth * 0.9f / Portrait.size.X;
Vector2 offset = Portrait.size * backgroundScale / 4;
if (Head.SheetIndex.HasValue)
{
Portrait.SourceRect = new Rectangle(CalculateOffset(Portrait, Head.SheetIndex.Value.ToPoint()), Portrait.SourceRect.Size);
}
Portrait.Draw(spriteBatch, screenPos + offset, scale: scale, spriteEffect: SpriteEffects.FlipHorizontally);
if (AttachmentSprites != null)
{
@@ -170,16 +192,21 @@ namespace Barotrauma
public void DrawIcon(SpriteBatch spriteBatch, Vector2 screenPos, Vector2 targetAreaSize)
{
if (HeadSprite != null)
var headSprite = HeadSprite;
if (headSprite != null)
{
float scale = Math.Min(targetAreaSize.X / HeadSprite.size.X, targetAreaSize.Y / HeadSprite.size.Y);
HeadSprite.Draw(spriteBatch, screenPos, scale: scale);
float scale = Math.Min(targetAreaSize.X / headSprite.size.X, targetAreaSize.Y / headSprite.size.Y);
if (Head.SheetIndex.HasValue)
{
headSprite.SourceRect = new Rectangle(CalculateOffset(headSprite, Head.SheetIndex.Value.ToPoint()), headSprite.SourceRect.Size);
}
headSprite.Draw(spriteBatch, screenPos, scale: scale);
if (AttachmentSprites != null)
{
float depthStep = 0.000001f;
foreach (var attachment in AttachmentSprites)
{
DrawAttachmentSprite(spriteBatch, attachment, HeadSprite, screenPos, scale, depthStep);
DrawAttachmentSprite(spriteBatch, attachment, headSprite, screenPos, scale, depthStep);
depthStep += depthStep;
}
}
@@ -188,13 +215,15 @@ namespace Barotrauma
private void DrawAttachmentSprite(SpriteBatch spriteBatch, WearableSprite attachment, Sprite head, Vector2 drawPos, float scale, float depthStep, SpriteEffects spriteEffects = SpriteEffects.None)
{
var list = AttachmentSprites.ToList();
if (attachment.InheritSourceRect)
{
if (attachment.SheetIndex.HasValue)
{
Point location = (head.SourceRect.Location + head.SourceRect.Size) * attachment.SheetIndex.Value;
attachment.Sprite.SourceRect = new Rectangle(location, head.SourceRect.Size);
attachment.Sprite.SourceRect = new Rectangle(CalculateOffset(head, attachment.SheetIndex.Value), head.SourceRect.Size);
}
else if (Head.SheetIndex.HasValue)
{
attachment.Sprite.SourceRect = new Rectangle(CalculateOffset(head, Head.SheetIndex.Value.ToPoint()), head.SourceRect.Size);
}
else
{
@@ -219,7 +248,6 @@ namespace Barotrauma
attachment.Sprite.Draw(spriteBatch, drawPos, Color.White, origin, rotate: 0, scale: scale, depth: depth, spriteEffect: spriteEffects);
}
public static CharacterInfo ClientRead(string speciesName, IReadMessage inc)
{
ushort infoID = inc.ReadUInt16();
@@ -234,6 +262,8 @@ namespace Barotrauma
string ragdollFile = inc.ReadString();
string jobIdentifier = inc.ReadString();
int variant = inc.ReadByte();
JobPrefab jobPrefab = null;
Dictionary<string, float> skillLevels = new Dictionary<string, float>();
if (!string.IsNullOrEmpty(jobIdentifier))
@@ -249,7 +279,7 @@ namespace Barotrauma
}
// TODO: animations
CharacterInfo ch = new CharacterInfo(speciesName, newName, jobPrefab, ragdollFile)
CharacterInfo ch = new CharacterInfo(speciesName, newName, jobPrefab, ragdollFile, variant)
{
ID = infoID,
};
@@ -249,7 +249,7 @@ namespace Barotrauma
msg.ReadPadBits();
int index = 0;
if (GameMain.Client.Character == this && AllowInput)
if (GameMain.Client.Character == this && CanMove)
{
var posInfo = new CharacterStateInfo(
pos, rotation,
@@ -309,7 +309,7 @@ namespace Barotrauma
LastNetworkUpdateID = controlled.LastNetworkUpdateID;
}
Controlled = this;
if (!IsDead) { Controlled = this; }
IsRemotePlayer = false;
GameMain.Client.HasSpawned = true;
GameMain.Client.Character = this;
@@ -342,7 +342,7 @@ namespace Barotrauma
}
}
public static Character ReadSpawnData(IReadMessage inc, bool spawn = true)
public static Character ReadSpawnData(IReadMessage inc)
{
DebugConsole.Log("Reading character spawn data");
@@ -362,10 +362,9 @@ namespace Barotrauma
Character character = null;
if (noInfo)
{
if (!spawn) return null;
character = Create(speciesName, position, seed, null, true);
character.ID = id;
character.ReadStatus(inc);
}
else
{
@@ -375,15 +374,14 @@ namespace Barotrauma
bool hasAi = inc.ReadBoolean();
string infoSpeciesName = inc.ReadString();
if (!spawn) return null;
CharacterInfo info = CharacterInfo.ClientRead(infoSpeciesName, inc);
character = Create(infoSpeciesName, position, seed, info, GameMain.Client.ID != ownerId, hasAi);
character = Create(speciesName, position, seed, info, GameMain.Client.ID != ownerId, hasAi);
character.ID = id;
character.TeamID = (TeamType)teamID;
character.ReadStatus(inc);
if (character.IsHuman && character.TeamID != TeamType.FriendlyNPC)
if (character.IsHuman && character.TeamID != TeamType.FriendlyNPC && !character.IsDead)
{
CharacterInfo duplicateCharacterInfo = GameMain.GameSession.CrewManager.GetCharacterInfos().FirstOrDefault(c => c.ID == info.ID);
GameMain.GameSession.CrewManager.RemoveCharacterInfo(duplicateCharacterInfo);
@@ -394,7 +392,7 @@ namespace Barotrauma
{
GameMain.Client.HasSpawned = true;
GameMain.Client.Character = character;
Controlled = character;
if (!character.IsDead) { Controlled = character; }
GameMain.LightManager.LosEnabled = true;
@@ -13,7 +13,7 @@ namespace Barotrauma
{
private static bool toggledThisFrame;
private static Sprite damageOverlay;
public static Sprite DamageOverlay;
private static string[] strengthTexts;
@@ -153,12 +153,7 @@ namespace Barotrauma
get { return healthBarPulsateTimer; }
set { healthBarPulsateTimer = MathHelper.Clamp(value, 0.0f, 10.0f); }
}
static CharacterHealth()
{
damageOverlay = new Sprite("Content/UI/damageOverlay.png", Vector2.Zero);
}
partial void InitProjSpecific(XElement element, Character character)
{
DisplayedVitality = MaxVitality;
@@ -837,8 +832,8 @@ namespace Barotrauma
if (damageOverlayAlpha > 0.0f)
{
damageOverlay.Draw(spriteBatch, Vector2.Zero, Color.White * damageOverlayAlpha, Vector2.Zero, 0.0f,
new Vector2(GameMain.GraphicsWidth / damageOverlay.size.X, GameMain.GraphicsHeight / damageOverlay.size.Y));
DamageOverlay?.Draw(spriteBatch, Vector2.Zero, Color.White * damageOverlayAlpha, Vector2.Zero, 0.0f,
new Vector2(GameMain.GraphicsWidth / DamageOverlay.size.X, GameMain.GraphicsHeight / DamageOverlay.size.Y));
}
if (Character.Inventory != null)
@@ -997,30 +992,7 @@ namespace Barotrauma
//key = item identifier
//float = suitability
Dictionary<string, float> treatmentSuitability = new Dictionary<string, float>();
float minSuitability = -10, maxSuitability = 10;
foreach (Affliction affliction in afflictions)
{
foreach (KeyValuePair<string, float> treatment in affliction.Prefab.TreatmentSuitability)
{
if (!treatmentSuitability.ContainsKey(treatment.Key))
{
treatmentSuitability[treatment.Key] = treatment.Value * affliction.Strength;
}
else
{
treatmentSuitability[treatment.Key] += treatment.Value * affliction.Strength;
}
minSuitability = Math.Min(treatmentSuitability[treatment.Key], minSuitability);
maxSuitability = Math.Max(treatmentSuitability[treatment.Key], maxSuitability);
}
}
//normalize the suitabilities to a range of 0 to 1
foreach (string treatment in treatmentSuitability.Keys.ToList())
{
treatmentSuitability[treatment] = (treatmentSuitability[treatment] - minSuitability) / (maxSuitability - minSuitability);
//lerp towards a random value if the medical skill is low
treatmentSuitability[treatment] = MathHelper.Lerp(treatmentSuitability[treatment], Rand.Range(0.0f, 1.0f), randomVariance);
}
GetSuitableTreatments(treatmentSuitability, normalize: true, randomization: randomVariance);
foreach (Affliction affliction in afflictions)
{
@@ -2,7 +2,7 @@
{
partial class DamageModifier
{
[Serialize("", false)]
[Serialize("", false), Editable]
public string DamageSound
{
get;
@@ -119,7 +119,24 @@ namespace Barotrauma
public List<SpriteDeformation> Deformations { get; private set; } = new List<SpriteDeformation>();
public Sprite Sprite { get; protected set; }
public DeformableSprite DeformSprite { get; protected set; }
protected DeformableSprite _deformSprite;
public DeformableSprite DeformSprite
{
get
{
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.IsActive && c.DeformableSprite != null);
if (conditionalSprite != null)
{
return conditionalSprite.DeformableSprite;
}
else
{
return _deformSprite;
}
}
}
public List<DecorativeSprite> DecorativeSprites { get; private set; } = new List<DecorativeSprite>();
@@ -127,15 +144,14 @@ namespace Barotrauma
{
get
{
// TODO: should we optimize this? No need to check all the conditionals each time the property is accessed.
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.IsActive);
var conditionalSprite = ConditionalSprites.FirstOrDefault(c => c.IsActive && c.ActiveSprite != null);
if (conditionalSprite != null)
{
return conditionalSprite;
return conditionalSprite.ActiveSprite;
}
else
{
return DeformSprite != null ? DeformSprite.Sprite : Sprite;
return _deformSprite != null ? _deformSprite.Sprite : Sprite;
}
}
}
@@ -215,40 +231,53 @@ namespace Barotrauma
DamagedSprite = new Sprite(subElement, file: GetSpritePath(subElement, Params.damagedSpriteParams));
break;
case "conditionalsprite":
ConditionalSprites.Add(new ConditionalSprite(subElement, character, file: GetSpritePath(subElement, null)));
var conditionalSprite = new ConditionalSprite(subElement, character, file: GetSpritePath(subElement, null));
ConditionalSprites.Add(conditionalSprite);
if (conditionalSprite.DeformableSprite != null)
{
CreateDeformations(subElement.GetChildElement("deformablesprite"));
}
break;
case "deformablesprite":
DeformSprite = new DeformableSprite(subElement, filePath: GetSpritePath(subElement, Params.deformSpriteParams));
foreach (XElement animationElement in subElement.Elements())
{
int sync = animationElement.GetAttributeInt("sync", -1);
SpriteDeformation deformation = null;
if (sync > -1)
{
// if the element is marked with the sync attribute, use a deformation of the same type with the same sync value, if there is one already.
string typeName = animationElement.GetAttributeString("type", "").ToLowerInvariant();
deformation = ragdoll.Limbs
.Where(l => l != null)
.SelectMany(l => l.Deformations)
.Where(d => d.TypeName == typeName && d.Sync == sync)
.FirstOrDefault();
}
if (deformation == null)
{
deformation = SpriteDeformation.Load(animationElement, character.SpeciesName);
if (deformation != null)
{
ragdoll.SpriteDeformations.Add(deformation);
}
}
if (deformation != null) Deformations.Add(deformation);
}
_deformSprite = new DeformableSprite(subElement, filePath: GetSpritePath(subElement, Params.deformSpriteParams));
CreateDeformations(subElement);
break;
case "lightsource":
LightSource = new LightSource(subElement);
InitialLightSourceColor = LightSource.Color;
break;
}
void CreateDeformations(XElement e)
{
foreach (XElement animationElement in e.GetChildElements("spritedeformation"))
{
int sync = animationElement.GetAttributeInt("sync", -1);
SpriteDeformation deformation = null;
if (sync > -1)
{
// if the element is marked with the sync attribute, use a deformation of the same type with the same sync value, if there is one already.
string typeName = animationElement.GetAttributeString("type", "").ToLowerInvariant();
deformation = ragdoll.Limbs
.Where(l => l != null)
.SelectMany(l => l.Deformations)
.Where(d => d.TypeName == typeName && d.Sync == sync)
.FirstOrDefault();
}
if (deformation == null)
{
deformation = SpriteDeformation.Load(animationElement, character.SpeciesName);
if (deformation != null)
{
ragdoll.SpriteDeformations.Add(deformation);
}
}
if (deformation != null)
{
Deformations.Add(deformation);
}
}
}
}
}
@@ -260,11 +289,11 @@ namespace Barotrauma
var source = Sprite.SourceElement;
Sprite = new Sprite(source, file: GetSpritePath(source, Params.normalSpriteParams));
}
if (DeformSprite != null)
if (_deformSprite != null)
{
DeformSprite.Remove();
var source = DeformSprite.Sprite.SourceElement;
DeformSprite = new DeformableSprite(source, filePath: GetSpritePath(source, Params.deformSpriteParams));
_deformSprite.Remove();
var source = _deformSprite.Sprite.SourceElement;
_deformSprite = new DeformableSprite(source, filePath: GetSpritePath(source, Params.deformSpriteParams));
}
if (DamagedSprite != null)
{
@@ -275,9 +304,8 @@ namespace Barotrauma
for (int i = 0; i < ConditionalSprites.Count; i++)
{
var conditionalSprite = ConditionalSprites[i];
var source = conditionalSprite.ActiveSprite.SourceElement;
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++)
@@ -289,6 +317,12 @@ namespace Barotrauma
}
}
private void CalculateHeadPosition(Sprite sprite)
{
if (type != LimbType.Head) { return; }
character.Info?.CalculateHeadPosition(sprite);
}
private string GetSpritePath(XElement element, SpriteParams spriteParams)
{
string texturePath = element.GetAttributeString("texture", null);
@@ -330,7 +364,7 @@ namespace Barotrauma
bool isFlipped = dir == Direction.Left;
Sprite?.LoadParams(Params.normalSpriteParams, isFlipped);
DamagedSprite?.LoadParams(Params.damagedSpriteParams, isFlipped);
DeformSprite?.Sprite.LoadParams(Params.deformSpriteParams, isFlipped);
_deformSprite?.Sprite.LoadParams(Params.deformSpriteParams, isFlipped);
for (int i = 0; i < DecorativeSprites.Count; i++)
{
DecorativeSprites[i].Sprite?.LoadParams(Params.decorativeSpriteParams[i], isFlipped);
@@ -461,24 +495,31 @@ namespace Barotrauma
enableHuskSprite && HuskSprite != null && HuskSprite.HideLimb ||
OtherWearables.Any(w => w.HideLimb) ||
wearingItems.Any(w => w != null && w.HideLimb);
var activeSprite = ActiveSprite;
if (type == LimbType.Head)
{
CalculateHeadPosition(activeSprite);
}
// TODO: there's now two calls to this, because body.Draw() method calls this too -> is this an issue?
body.UpdateDrawPosition();
if (!hideLimb)
{
var activeSprite = ActiveSprite;
if (DeformSprite != null && activeSprite == DeformSprite.Sprite)
var deformSprite = DeformSprite;
if (deformSprite != null)
{
if (Deformations != null && Deformations.Any())
{
var deformation = SpriteDeformation.GetDeformation(Deformations, DeformSprite.Size);
DeformSprite.Deform(deformation);
var deformation = SpriteDeformation.GetDeformation(Deformations, deformSprite.Size);
deformSprite.Deform(deformation);
}
else
{
DeformSprite.Reset();
deformSprite.Reset();
}
body.Draw(DeformSprite, cam, Vector2.One * Scale * TextureScale, color, Params.MirrorHorizontally);
body.Draw(deformSprite, cam, Vector2.One * Scale * TextureScale, color, Params.MirrorHorizontally);
}
else
{
@@ -489,15 +530,16 @@ namespace Barotrauma
if (LightSource != null)
{
LightSource.Position = body.DrawPosition;
if (LightSource.ParentSub != null) { LightSource.Position -= LightSource.ParentSub.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,
color * Math.Min(damageOverlayStrength, 1.0f), activeSprite.Origin,
-body.DrawRotation,
Scale, spriteEffect, ActiveSprite.Depth - 0.0000015f);
Scale, spriteEffect, activeSprite.Depth - 0.0000015f);
}
foreach (var decorativeSprite in DecorativeSprites)
{
@@ -636,48 +678,58 @@ namespace Barotrauma
{
foreach (var modifier in damageModifiers)
{
float rotation = -body.TransformedRotation + GetArmorSectorRotationOffset(modifier.ArmorSectorInRadians) * Dir;
Vector2 forward = VectorExtensions.Forward(rotation);
//Vector2 up = VectorExtensions.Backward(-body.TransformedRotation + Params.GetSpriteOrientation() * Dir);
//int width = 4;
//if (!isScreenSpace)
//{
// width = (int)Math.Round(width / cam.Zoom);
//}
//GUI.DrawLine(spriteBatch, startPos, startPos + Vector2.Normalize(up) * size, Color.Red, width: width);
Color color = modifier.DamageMultiplier > 1 ? Color.Red : Color.GreenYellow;
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);
float bodyRotation = -body.Rotation;
float constantOffset = -MathHelper.PiOver2;
Vector2 armorSector = modifier.ArmorSectorInRadians;
float armorSectorSize = Math.Abs(armorSector.X - armorSector.Y);
float radians = armorSectorSize * Dir;
float armorSectorOffset = armorSector.X * Dir;
float finalOffset = bodyRotation + constantOffset + armorSectorOffset;
ShapeExtensions.DrawSector(spriteBatch, startPos, size, radians, 40, color, finalOffset, thickness);
}
}
private void DrawWearable(WearableSprite wearable, float depthStep, SpriteBatch spriteBatch, Color color, SpriteEffects spriteEffect)
{
var sprite = ActiveSprite;
if (wearable.InheritSourceRect)
{
if (wearable.SheetIndex.HasValue)
{
Point location = (ActiveSprite.SourceRect.Location + ActiveSprite.SourceRect.Size) * wearable.SheetIndex.Value;
wearable.Sprite.SourceRect = new Rectangle(location, ActiveSprite.SourceRect.Size);
wearable.Sprite.SourceRect = new Rectangle(CharacterInfo.CalculateOffset(sprite, wearable.SheetIndex.Value), sprite.SourceRect.Size);
}
else if (type == LimbType.Head && character.Info != null && character.Info.Head.SheetIndex.HasValue)
{
wearable.Sprite.SourceRect = new Rectangle(CharacterInfo.CalculateOffset(sprite, character.Info.Head.SheetIndex.Value.ToPoint()), sprite.SourceRect.Size);
}
else
{
wearable.Sprite.SourceRect = ActiveSprite.SourceRect;
wearable.Sprite.SourceRect = sprite.SourceRect;
}
}
Vector2 origin = wearable.Sprite.Origin;
if (wearable.InheritOrigin)
{
origin = ActiveSprite.Origin;
origin = sprite.Origin;
wearable.Sprite.Origin = origin;
}
else
@@ -694,7 +746,7 @@ namespace Barotrauma
if (wearable.InheritLimbDepth)
{
depth = ActiveSprite.Depth - depthStep;
depth = sprite.Depth - depthStep;
Limb depthLimb = (wearable.DepthLimb == LimbType.None) ? this : character.AnimController.GetLimb(wearable.DepthLimb);
if (depthLimb != null)
{
@@ -728,11 +780,11 @@ namespace Barotrauma
XElement element;
if (random)
{
element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), type)?.FirstOrDefault();
element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), type)?.GetRandom(Rand.RandSync.ClientOnly);
}
else
{
element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), type)?.GetRandom(Rand.RandSync.ClientOnly);
element = info.FilterByTypeAndHeadID(character.Info.FilterElementsByGenderAndRace(character.Info.Wearables), type)?.FirstOrDefault();
}
if (element != null)
{
@@ -749,8 +801,8 @@ namespace Barotrauma
DamagedSprite?.Remove();
DamagedSprite = null;
DeformSprite?.Sprite?.Remove();
DeformSprite = null;
_deformSprite?.Sprite?.Remove();
_deformSprite = null;
DecorativeSprites.ForEach(s => s.Remove());
ConditionalSprites.Clear();